Docker error during connect docker_engine in CI
Docker error during connect docker_engine on a Windows named pipe means the CLI never reached a daemon at all: it tried to open the pipe the engine listens on and found nothing there. On a Windows runner the reasons are short: the engine is not running yet, the client is pointed somewhere else, or the job wanted Linux containers and is on the wrong runner.

What this error means
Every Docker command in the job fails the same way and fails instantly, including docker version and docker info, because nothing ever reached the engine. The URL in the message is the pipe path percent-encoded, which is what makes it look exotic: %2F%2F.%2Fpipe%2Fdocker_engine is just //./pipe/docker_engine. The Windows CLI talks to the engine over the npipe transport, written npipe:////./pipe/docker_engine, where Linux and macOS use unix:///var/run/docker.sock. The API version in that URL is whatever the client speaks, so it varies with the Docker version on the runner; the line below shows v1.24, because it is quoted from docker/for-win#13137 rather than from a run of ours. We have no recorded run for this one: our harness runs Linux latchkey-small runners.
error during connect: This error may indicate that the docker daemon is not running.: Get "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/containers/json": open //./pipe/docker_engine: The system cannot find the file specified.What the client is actually trying to open
The Docker CLI decides where to send a request from the active context, or from DOCKER_HOST, and DOCKER_CONTEXT overrides DOCKER_HOST and the context set with docker context use. On Windows the endpoint is a named pipe; the documented scheme is npipe://[<name>], with npipe:////./pipe/docker_engine as the example. A pipe is created by the process that serves it, so it is absent whenever the engine is not up.
That gives you two checks and they take seconds. Ask which endpoint the client would use, then ask whether the service behind it is running.
| Check | What it tells you |
|---|---|
docker context ls | Which endpoint the client will use, and which context is active |
Get-Service docker | Whether the engine is running at all on this machine |
echo $env:DOCKER_HOST | Whether something earlier in the job redirected the client |
docker version | Whether the failure is transport or something later in the API call |
Common causes
The engine is not running yet
The most common cause on a hosted Windows runner, and the reason the error can be intermittent: the first step runs before the service is ready, and a rerun of the same workflow passes. The error text itself hints at it, telling you the daemon may not be running.
The client is pointed at another endpoint
A DOCKER_HOST exported by an earlier step, a context created for a remote builder, or a leftover context from a tool that set one all send the request somewhere with no listener. DOCKER_CONTEXT wins over DOCKER_HOST, so both have to be checked rather than one.
The job needs Linux containers and is on Windows
Service containers, job containers and Docker-based actions are Linux-only on GitHub runners. In our experience this is the cause when the error appears the same day somebody added services: to a Windows job, and no amount of engine restarting changes it.
The user in the step cannot open the pipe
A variant of the same message reads "Access is denied" instead of "cannot find the file specified", which is a permission problem rather than a missing engine. docker/for-win#14716 reports it for a secondary user account. The fix is the account or group membership, not the service.
How to fix it
Start the engine as the first step, and wait for it to answer
- Run
Start-Service dockerbefore anything that uses Docker. - Poll
docker versionuntil it returns, with a short sleep between attempts. - Print
docker infoonce so the log records which container mode is active.
Start-Service docker
docker version
docker info --format "{{.OSType}}"Check the context before blaming the daemon
List the contexts and read the endpoint column. If the active context points at anything other than the local pipe, switch it explicitly in the job rather than relying on whatever the image or a previous step left behind.
docker context ls
docker context use defaultMove Linux-container work to a Linux runner
Service containers, job containers and container actions need a Linux runner on GitHub. Split the job: keep the Windows-specific steps on windows-latest and run the containerized parts on ubuntu-latest, rather than trying to reproduce Linux behavior on Windows.
jobs:
windows-build:
runs-on: windows-latest
linux-integration:
runs-on: ubuntu-latest
services:
redis:
image: redis:7Read which half of the message you have
The two endings are two different problems. "The system cannot find the file specified" means no pipe, so the engine is not running. "Access is denied" means the pipe is there and this account may not open it, which points at the user the step runs as.
docker version 2>&1 | Select-String "pipe/docker_engine"On a Windows runner, start the service and wait for it
The runner image ships Docker: the windows-2025 image README listed Docker 29.7.2 and Docker Compose 2.40.3 when we read it on 2026-09-20. What it does not promise is that the service is running and ready at the moment your first step executes. A start plus a short wait removes the whole class of flaky first-step failures, and it is idempotent, so it costs nothing when the engine was already up.
Wait for the engine to answer rather than for a fixed number of seconds. A sleep long enough to be safe is long enough to be a tax on every job.
- name: Make sure the engine is up
shell: pwsh
run: |
Start-Service docker -ErrorAction SilentlyContinue
$deadline = (Get-Date).AddMinutes(2)
while ((Get-Date) -lt $deadline) {
docker version --format "{{.Server.Version}}" 2>&1 | Out-Host
if ($LASTEXITCODE -eq 0) { break }
Start-Sleep -Seconds 3
}
docker info --format "{{.OSType}} containers"Many jobs that hit this belong on a Linux runner
GitHub is explicit about the limits, in the page we read on 2026-09-20: if your workflows use Docker container actions, job containers or service containers, then you must use a Linux runner, and on GitHub-hosted runners that means an Ubuntu runner. A workflow that grew a container: key or a services: block on a Windows job has a problem no engine start will fix.
The question to ask is what the containers are for. Building or testing Windows containers needs a Windows runner. Everything else, including almost every service container and every Docker-based action, runs on Linux, and moving the job is less work than making Windows behave like Linux.
jobs:
integration:
runs-on: ubuntu-latest # services: and container: need Linux
services:
postgres:
image: postgres:17What the runner does about it
Nothing here, and the honest reason is that this is not a failure our runners see: Latchkey runner labels are Linux, latchkey-small through latchkey-xlarge, so a job on one of them talks to a unix socket and never opens a named pipe. That is also why this page carries no reproduction and does not pretend to.
If your Windows jobs exist to build Windows containers, keep them on Windows and add the engine check above as the first step. If they exist because the workflow was written on a Windows laptop, moving them to Linux removes this error and usually several minutes of startup with it.
How to prevent it
- Start and health-check the engine as the first step of every Windows job.
- Keep service containers and container actions on Linux runners.
- Set the context explicitly when any step in the job creates one.
- Print the Docker version and OS type once per job, so the log answers the first question.
Frequently asked questions
What is //./pipe/docker_engine?
npipe:////./pipe/docker_engine. The CLI percent-encodes it into the request URL, which is why the error looks like a broken HTTP address. A pipe only exists while the process serving it is running.Can I run Linux containers on a windows-latest runner?
Why does the error appear in one step and not the next?
DOCKER_HOST exported in a script affects only that step.Is this the same as permission denied on docker.sock?
Related guides
References
- Docker docs: the docker CLI, DOCKER_HOST, DOCKER_CONTEXT and the npipe scheme
- GitHub docs: service containers require a Linux runner
- actions/runner-images: the windows-2025 image contents
- docker/for-win#13137: the system cannot find the file specified on the engine pipe
- Docker documentation
- Docker build cache
- GitHub Actions documentation