# Docker failed to create shim task executable file not found in CI

> Fix Docker failed to create shim task executable file not found in GitHub Actions: the image cannot run the command it was told to start.

Source: https://latchkey.dev/learn/docker/docker-failed-to-create-shim-task-not-found  
Updated: 2026-09-20

Docker failed to create shim task executable file not found means the container never started, because the process it was told to run does not exist inside the image. The shim and runc are reporting faithfully: everything up to the exec worked, and the binary named by your command, CMD or ENTRYPOINT is not there.

## What this error means

A `docker run`, a `docker compose up` or a Kubernetes pod start fails immediately, with a long error that reads like an infrastructure fault and is not one. The chain is the point: the daemon could not create the task, containerd could not create the shim task, the OCI runtime could not create the container, and runc could not start the process, because the executable is missing. Our recorded run on Docker 29.7.2 ended the chain with "error during container init: exec: \"yarn\": executable file not found in $PATH" and exited 127; older daemons print the same thing with a trailing ": unknown", which is the form moby/moby#47847 reports.

```Actions log, run step, Docker 29.7.2
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: exec: "yarn": executable file not found in $PATH
```

## Common causes

### The final stage never installed the tool

The dominant cause in CI. The builder stage had it, the runtime stage did not, and nothing failed until the container tried to start. In our experience it arrives the week somebody slims an image, and the commit that broke it looks like a pure improvement.

### The entrypoint script was not copied, or is not executable

A `docker-entrypoint.sh` that the COPY missed produces this exact error with the script name in the quotes. A copied script without the executable bit produces a permission error instead, which is a useful distinction: not found is the COPY, permission denied is the mode.

### The command names a shell built-in or a shell line

Exec form does not go through a shell, and Docker documents that: the exec form does not invoke a command shell, so normal shell processing such as variable substitution does not happen. A CMD written as `["npm start && node server.js"]` names one impossible executable.

### The binary is for a different architecture

A binary built for amd64 in an arm64 image can fail to exec, and the message is not always the clear one about exec format. When a tool is visibly present in the image and still will not start, check the architecture of both before you go further.

## How to fix it

### Install the runtime tool in the stage that ships

1. Move the install into the final stage, or copy the tool out of the builder explicitly.
2. Keep the CMD naming exactly what that stage provides.
3. Rebuild and run the image once with no arguments, locally or in the job.

```Dockerfile
FROM node:22-bookworm-slim
COPY --from=build /app /app
RUN corepack enable
CMD ["yarn", "start"]
```

### Use an absolute path in CMD and ENTRYPOINT

An absolute path removes PATH from the question, and it documents where the binary is meant to be. It also makes a broken COPY obvious: the error names a path you can check rather than a bare name you have to hunt for.

```Dockerfile
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["/usr/local/bin/node", "server.js"]
```

### Give shell syntax a shell

If the command needs a pipe, a variable or a chain, call a shell explicitly in the exec form. That keeps signal handling sane and makes the shell a deliberate choice rather than an accident of the form you typed.

```Dockerfile
CMD ["sh", "-c", "node server.js --port \"$PORT\""]
```

### Smoke run every image before anything depends on it

Run the built image once in the build job, with its real command. It catches a missing entrypoint, a missing tool and a wrong architecture in seconds, at the point where the person who broke it is still looking at the pipeline.

```Terminal
docker run --rm "$IMAGE" --version
docker run --rm --entrypoint sh "$IMAGE" -c 'ls -l /usr/local/bin | head'
```

## How to prevent it

- Smoke run the image in the same job that builds it.
- Keep runtime tools in the final stage, and say so in a comment next to the COPY.
- Prefer absolute paths in ENTRYPOINT and CMD.
- Build and test the same platform you deploy, or test both explicitly.

## Read the chain backwards

The error names four layers because four layers passed the failure up. The daemon asked containerd for a task, containerd started a shim, the shim called the OCI runtime, and runc tried to exec the process. Everything in that list worked. The only clause that carries information is the last one, and it names a binary.

This is why searching the first half of the message finds pages about containerd versions, kernel settings and runtime bugs that have nothing to do with your build. Search the last clause instead, with the binary name in it.

| Clause | What it actually tells you |
| --- | --- |
| `failed to create task for container` | The daemon is reporting the layer below it, nothing more |
| `failed to create shim task` | containerd started its shim and the shim reported a failure |
| `OCI runtime create failed: runc create failed` | runc got as far as setting up the container process |
| `exec: "yarn": executable file not found in $PATH` | The whole diagnosis: that binary is not in the image |

> The neighboring error from `docker exec` reads almost the same and means something else: [OCI runtime exec failed](/learn/docker/docker-oci-runtime-exec-failed) is a running container refusing an extra command.

## Multi-stage builds are where the binary goes missing

A build stage installs a toolchain, the final stage copies an artifact out of it, and the tool the CMD names stays behind in the stage that was thrown away. The image is small and correct right up to the moment something tries to run the command, which is why the build is green and the run is not.

The same shape appears with a CMD that names a package manager, a task runner or an entrypoint script: yarn, pnpm, make, or `docker-entrypoint.sh` when the COPY that was meant to bring it in did not. moby/moby#47847 is exactly that last one.

```Dockerfile
# the binary has to exist in the stage that ships
FROM node:22-bookworm AS build
RUN corepack enable && yarn install && yarn build

FROM node:22-bookworm-slim
COPY --from=build /app/dist /app/dist
RUN corepack enable          # without this, CMD ["yarn", ...] fails at run time
CMD ["yarn", "start"]
```

## Prove it in the job, in one line

The cheapest test is to run the image with a shell instead of its command and ask the container what it can resolve. If `command -v` finds nothing, the image is the problem and no amount of workflow change will help. If it finds the binary, your CMD is naming something else, most often through a typo or a path that only existed in a builder stage.

Do this in the same job, right after the build, so a broken image never reaches a deploy step. A smoke run costs a few seconds against a build that already took minutes.

```.github/workflows/ci.yml
- name: Smoke test the image command
  run: |
    docker run --rm --entrypoint sh "$IMAGE" -c 'command -v yarn && yarn --version'
    docker run --rm "$IMAGE" --help
```

## What the runner does about it

No repair, and none is claimed. On the recorded run the wrapper posted the failure to the sidecar and the sidecar answered, and no repair followed: an image without yarn does not gain yarn between attempts. Latchkey carries no pattern for this one, and adding one would mean editing somebody else's image from the outside, which is not a repair anybody should want.

What the reproduction does show is how cheap the diagnosis is. The control run in the same script starts a container from the same image with a binary it does have, so the log proves the daemon, the shim and the image are all healthy before it shows the create failing. That contrast is worth copying into your own workflow.

The control line is also why this script ran twice. On the first attempt it piped `docker run ... busybox --help` into `head -1`, and under `set -o pipefail` the closed pipe turned into SIGPIPE and a 141 verdict before the failing command ever ran. The control now prints its own single line and nothing pipes; that one line is the only difference between the two attempts, and the log above is the second.

## FAQ

### What does failed to create shim task actually mean?

That containerd asked its shim to create the container task and the attempt failed. On its own it says nothing about the cause; the clause at the end of the chain does. When that clause is "executable file not found in $PATH", the container never started because the process it was told to run is not in the image.

### Why does the build pass and the container fail to start?

Because a build checks that your instructions ran, not that the final image can run its own command. A multi-stage build that installs a tool in the builder and copies only artifacts out produces a perfectly valid image whose CMD names something that is no longer there. A smoke run in the same job catches it.

### Is this the same as OCI runtime exec failed?

No. Create failed is the container not starting, so the fix is in the image. Exec failed is a running container refusing an extra command from `docker exec`, so the fix is in the command or in the container state.

### What does ": unknown" at the end of a Docker runtime error mean?

It is the daemon saying the layer below it gave no error type it recognizes, and it is a daemon-version difference rather than a clue. Our run on Docker 29.7.2 ended at "executable file not found in $PATH"; the older wording appends ": unknown", which is what moby/moby#47847 and most search results show. Both are the same failure, so match on the "executable file not found" part in any log check you write.

## References

- [Docker docs: Dockerfile reference, CMD and ENTRYPOINT forms](https://docs.docker.com/reference/dockerfile/)
- [Docker docs: docker exec and the running container requirement](https://docs.docker.com/reference/cli/docker/container/exec/)
- [moby/moby#47847: create failed on a missing docker-entrypoint.sh](https://github.com/moby/moby/issues/47847)

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
