Skip to content

[Bug]: On Linux, docker permission errors trigger systemctl start docker (polkit prompt) instead of surfacing the permission error #22255

@dlevy-msft-sql

Description

@dlevy-msft-sql

Summary

On Linux, when the extension's startDocker() cannot reach the Docker daemon, it cannot distinguish between "daemon stopped" and "daemon running but socket not accessible to this process" (EACCES on /var/run/docker.sock). It treats both as "daemon down" and tries to run systemctl start docker, which triggers a polkit authentication prompt and then fails with:

Docker failed to start within the timeout period. Please manually start Docker and try again.

…even though the daemon is already running fine and docker ps works in a normal terminal.

Repro

  1. Ubuntu 24.04, Docker Engine (system install, not Desktop), daemon active.
  2. Add your user to the docker group: sudo usermod -aG docker $USER.
  3. Launch VS Code without fully logging out of the GUI session first (so the VS Code process tree does not yet have docker in its supplementary groups, even though newgrp docker or a fresh terminal does).
  4. Open a SQL connection that goes through the extension's docker path (e.g. Local Container deployment, or any flow that calls startDocker).
  5. Observe:
    • polkit prompt: "Authentication is required to start 'docker.service'."
    • After a delay: notification "Docker failed to start within the timeout period…"
  6. Meanwhile in the integrated terminal: docker info and docker ps succeed without sudo, and systemctl is-active docker returns active.

Root cause (from the code)

In extensions/mssql/src/docker/dockerUtils.ts, startDocker() does:

try {
    await execDockerCommand(COMMANDS.CHECK_DOCKER_RUNNING()); // `docker info`
    return { success: true };
} catch {} // If this command fails, docker is not running, so we proceed to start it.

The catch {} swallows the error and assumes "not running." On Linux, docker info failing is overwhelmingly a permissions problem (permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock), not a stopped daemon. The extension then runs:

linux: { command: "systemctl", args: ["start", "docker"] }

…which on a desktop Linux box is intercepted by polkit, prompts for a password, "succeeds," but does not change the access problem, so the subsequent docker info polls keep failing until the 60s timeout. The user sees a generic "failed to start" message.

This is also why a full GUI logout/login (or a reboot) "fixes" it: the VS Code process tree finally inherits the new docker group membership and docker info works.

Expected behavior

On Linux, before falling through to systemctl start docker:

  1. Inspect the error from docker info. If stderr/exit looks like a permission/socket error (permission denied, dial unix /var/run/docker.sock: connect: permission denied, EACCES), surface a specific message — something like:

    Cannot access the Docker socket. Your user may not be in the docker group, or VS Code was started before group membership took effect. Run sudo usermod -aG docker $USER and then log out and back in (or reboot).

    …and do not attempt systemctl start docker.

  2. Only fall through to the start path when the failure is actually consistent with the daemon being down (e.g. Cannot connect to the Docker daemon … Is the docker daemon running? with no permission keyword, or socket file missing).

  3. Optional but nice: detect systemctl is-active docker first on Linux; if it returns active, the problem is definitely not "not running" and the extension shouldn't escalate to sudo.

Environment

  • OS: Ubuntu 24.04
  • Docker: Docker Engine (apt install), default context, daemon active, /var/run/docker.sock is srw-rw---- root:docker
  • vscode-mssql: latest released version at time of report
  • VS Code: stable

Additional notes

Even users who eventually figure it out (reboot, newgrp docker, restart-after-relogin) end up confused by the polkit prompt, since nothing in the extension UI hints that the issue is group membership rather than the daemon. Distinguishing EACCES would also avoid asking for root credentials to "fix" something that root credentials cannot fix.

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions