DEV Community

DeployLark
DeployLark

Posted on Originally published at deploylark.com

Docker Build: Fix failed to compute cache key: not found

Your docker build or docker compose build stops at a COPY line with failed to compute cache key: failed to calculate checksum of ref ...: "/package.json": not found. The file is right there in your project, so the message looks wrong. It isn't. The builder never received that file. The Docker build context docs put it in one line: "The build context is the set of files that your build can access." Anything outside that set, or filtered out of it, is "not found".

This guide reproduces every common cause on Docker Engine 29.9.3 with a small Node app and fixes each one. All output below comes from that lab run on November 13, 2026. The error is a classic. On that day the Stack Overflow question Docker gets error "failed to compute cache key: not found" had 636,533 views, How to include files outside of Docker's build context? had 629,103 and An error, "failed to solve with frontend dockerfile.v0" had 764,565.

The short version:

  • COPY paths resolve from the root of the build context, the last argument of docker build. Not from the Dockerfile's folder and not from your shell's folder.
  • If your Dockerfile sits in a subfolder, build with that folder as the context: docker build app, or set context: ./app in Compose.
  • If you use an allowlist .dockerignore (* then !file), add every file you COPY.
  • COPY ../something can't leave the context. Pass the folder with --build-context name=./path and use COPY --from=name.
  • For COPY --from=<stage>, build that stage with --target and look inside it to find the real path.

Table of contents

What failed to compute cache key means

BuildKit checksums every COPY source so it can decide whether the cached layer is still valid. To checksum a file it needs the file. When the path doesn't exist in the build context, the checksum fails and the whole build stops with "failed to compute cache key". The error names the path BuildKit looked for, relative to the context root.

This map shows the path a file takes to reach COPY and the five ways it gets lost:

Diagram of how files reach a Dockerfile COPY: docker build PATH sets the context root, .dockerignore removes files, named contexts add folders, then COPY reads from the result. Below it a table of five causes, wrong build context, .dockerignore excludes the file, path outside the context, wrong path in another stage and filename case, with how to spot and fix each

What the error looks like

The lab project has this layout. The Dockerfile, package.json and server.js live in app/, and a shared config file lives next to it:

shop/
├── app/
│   ├── Dockerfile
│   ├── package.json
│   └── server.js
└── shared/
    └── config.json
Enter fullscreen mode Exit fullscreen mode

The Dockerfile is as plain as it gets:

FROM node:24.22.3-alpine3.24
WORKDIR /app
COPY package.json ./
COPY server.js ./
RUN npm run build
CMD ["npm", "start"]
Enter fullscreen mode Exit fullscreen mode

Running the build from shop/ with -f app/Dockerfile . fails on both COPY lines:

#6 [3/5] COPY package.json ./
#6 ERROR: failed to calculate checksum of ref u7ril5urrzm4gaxcl1f3cs3fw::mc3ahjnoy3ee1gcvane9cej4q: "/package.json": not found
#7 [4/5] COPY server.js ./
#7 ERROR: failed to calculate checksum of ref u7ril5urrzm4gaxcl1f3cs3fw::mc3ahjnoy3ee1gcvane9cej4q: "/server.js": not found
ERROR: failed to build: failed to solve: failed to compute cache key: failed to calculate checksum of ref u7ril5urrzm4gaxcl1f3cs3fw::mc3ahjnoy3ee1gcvane9cej4q: "/server.js": not found
Enter fullscreen mode Exit fullscreen mode

Read the quoted path. "/package.json" means BuildKit looked for package.json at the root of the context, which was shop/. The file is at shop/app/package.json. The ref IDs are random and differ on every machine, so ignore them.

The legacy builder says it differently

With BuildKit turned off (DOCKER_BUILDKIT=0), Docker 29.9.3 first prints a deprecation notice and then a clearer message for the same mistake:

Step 3/6 : COPY package.json ./
COPY failed: file not found in build context or excluded by .dockerignore: stat package.json: file does not exist
Enter fullscreen mode Exit fullscreen mode

That message already lists the two main causes. Two neighbour errors look similar but happen before any COPY. A wrong Dockerfile name gives failed to read dockerfile: open dockerfile: no such file or directory, and a context folder that doesn't exist gives unable to prepare context: path "app/shared" not found. Those mean the -f path or the context path is wrong, not a file inside it. Also note that docker build --check reported "Check complete, no warnings found." for a Dockerfile with a broken COPY, so the build checks won't catch this.

Fix 1: build from the right context

The most common cause by far is a context that doesn't match the paths in the Dockerfile. The -f flag only tells Docker where the Dockerfile is. It doesn't move the context. The accepted answer on the Stack Overflow question explains why Visual Studio users hit this. GregHNZ wrote that Visual Studio does it this way: "Instead of launching docker build in the folder with the Dockerfile, it launches in the parent folder and specifies the Dockerfile with the -f option."

Terminal capture: docker build with -f app/Dockerfile and context dot from the repo root transfers 2B of context and fails with package.json and server.js not found, then docker build app succeeds and the container answers shop-api ok

docker build with -f

Pick one of two fixes and keep the Dockerfile and the command in agreement.

Make the folder with the files the context. The Dockerfile in that folder is found automatically:

docker build -t shop-api:1 app
Enter fullscreen mode Exit fullscreen mode

Or keep the repo root as the context and write every COPY source relative to it, COPY app/package.json ./ and so on, then build with docker build -f app/Dockerfile .. This is the layout Visual Studio generates for .NET projects, which is why its Dockerfiles have paths like COPY ["WorkerService2/WorkerService2.csproj", ...]. A Dockerfile written for one context breaks with the other, so the fix is to match them, not to move files around.

In the lab, the failing build's context step showed transferring context: 2B. After the fix the image built and the container answered shop-api ok.

Docker Compose context and dockerfile

Compose has the same trap. In build, the dockerfile path is relative to context, and COPY paths are relative to context too. This file fails exactly like the -f command above:

services:
  api:
    image: shop-api:compose
    build:
      context: .
      dockerfile: app/Dockerfile
Enter fullscreen mode Exit fullscreen mode

docker compose build api ends with failed to solve: failed to compute cache key: failed to calculate checksum of ref ...: "/package.json": not found. Point the context at the app folder and the dockerfile becomes a plain file name:

services:
  api:
    image: shop-api:compose
    build:
      context: ./app
      dockerfile: Dockerfile
Enter fullscreen mode Exit fullscreen mode

If you see /app/package.json in the error, as in this Compose question with 56,651 views, the Dockerfile copies app/package.json from a context that doesn't contain an app folder. Same fix.

Fix 2: check .dockerignore

The most upvoted answer on the same Visual Studio question, with 532 votes, points here. Ilia Reshetnikov wrote: "Check your .dockerignore file. Possible it ignores needed files for copy command and you get failed to compute cache key error." The usual culprit is an allowlist, where * ignores everything and ! lines add files back. Forget one file and COPY can't see it.

Terminal capture: a .dockerignore with star and an exception only for package.json makes COPY server.js fail with not found, a busybox build that copies the context lists only package.json, and after adding an exception for server.js the context lists both files and the build succeeds

List what the builder receives

You don't have to guess what survives .dockerignore. Build a throwaway image that copies the whole context and lists it. Save this as ctx.Dockerfile next to your project:

FROM busybox:1.37.0
COPY . /ctx
RUN find /ctx -type f | sort
Enter fullscreen mode Exit fullscreen mode

Then build it with the same context you use for the real image:

docker build --no-cache --progress=plain -f ctx.Dockerfile app 2>&1 | grep -E '^#[0-9]+ [0-9.]+ '
Enter fullscreen mode Exit fullscreen mode

With the .dockerignore set to * and !package.json, the lab printed a single line, /ctx/package.json. That explains the "/server.js": not found. Adding !server.js to the file made the listing show both files, and the real build passed. Keep --no-cache, otherwise the RUN step can come from cache and print nothing.

Per-Dockerfile ignore files

The ignore file must sit at the root of the context. The docs say: "When you run a build command, the build client looks for a file named .dockerignore in the root directory of the context." A .dockerignore inside app/ does nothing when the context is the repo root.

If one repo has several Dockerfiles that need different rules, name the ignore file after the Dockerfile and put it next to it, for example app/Dockerfile.ctx.dockerignore. The lab used that pattern for every variant. According to the same docs page, "A Dockerfile-specific ignore-file takes precedence over the .dockerignore file at the root of the build context if both exist." So when you debug, check both files.

Fix 3: files outside the build context

Monorepos often have shared config or libraries one level up. COPY ../shared/config.json ./config.json looks reasonable, but BuildKit doesn't let a build step leave its context.

Terminal capture: COPY ../shared/config.json fails with /shared/config.json not found, a build with --build-context shared=./shared and COPY --from=shared succeeds and the container reports config=shared-prod, and the same Dockerfile without --build-context fails trying to pull docker.io/library/shared

Why ../ doesn't work

Look at the path in the lab's error: "/shared/config.json": not found. The ../ is gone. BuildKit resolved the path inside the context, app/, where no shared folder exists. You get "not found", not a clear "outside the context" message, which is why this cause is easy to miss.

The old workaround was to move the context up to the repo root and rewrite every COPY path to match. That still works. Named contexts let you keep the small context instead.

Named build contexts

Buildx lets you pass extra folders as named contexts. Give the shared folder a name on the command line:

docker build --build-context shared=./shared -f app/Dockerfile.ctx -t shop-api:2 app
Enter fullscreen mode Exit fullscreen mode

Then copy from it by name in the Dockerfile:

FROM node:24.22.3-alpine3.24
WORKDIR /app
COPY package.json server.js ./
COPY --from=shared config.json ./config.json
RUN npm run build
CMD ["npm", "start"]
Enter fullscreen mode Exit fullscreen mode

The image built and the app printed config=shared-prod, read from the shared file. Run the same Dockerfile without --build-context and BuildKit treats shared as an image name. It failed with failed to resolve source metadata for docker.io/library/shared:latest: pull access denied. If you see a pull error for a name that isn't an image, a named context is missing.

Compose supports the same thing with additional_contexts, described in the Compose build reference. This file built and ran in the lab:

services:
  api:
    image: shop-api:compose
    build:
      context: ./app
      dockerfile: Dockerfile.ctx
      additional_contexts:
        shared: ./shared
    ports:
      - "3000:3000"
Enter fullscreen mode Exit fullscreen mode

Fix 4: multi-stage paths and filename case

The error isn't only about your local files. COPY --from=<stage> in a multi-stage build checksums files inside that stage, and a wrong path there produces the same message.

Terminal capture: a multi-stage build fails because COPY --from=build looks for /src/build/server.js, building only the build stage with --target and running find shows the file is in /src/dist, and after fixing the path the image builds and the container answers shop-api ok

Build one stage and look inside

In the lab, the build stage ran npm run build, which writes dist/server.js. The final stage asked for the wrong folder:

COPY --from=build /src/build/server.js ./server.js
Enter fullscreen mode Exit fullscreen mode

The error read "/src/build/server.js": not found. Note the absolute path. For --from, the path is inside the stage's filesystem, not your context. To see what the stage really contains, build only that stage and list it:

docker build --target build -t shop-api:build -f app/Dockerfile.multi app
docker run --rm shop-api:build find /src -type f
Enter fullscreen mode Exit fullscreen mode

The listing showed /src/dist/server.js. Changing the COPY to /src/dist/server.js fixed the build. Check the stage's build script or tool config whenever you change its output folder.

Filename case

Linux file names are case sensitive, and BuildKit on Linux treats them that way. In the lab, COPY Package.json server.js ./ failed with "/Package.json": not found even though package.json was right there. A wrong case can go unnoticed on a machine whose file system ignores case and only break when the image builds on Linux or in CI. Match the case of the file on disk exactly, and check .dockerignore patterns for the same problem.

If none of the four fixes apply and your build stops later with a different error, the exec format error guide covers broken entrypoints and wrong architectures. If builds fail because the disk is full, see Docker no space left on device. For permission denied on /var/run/docker.sock when you run the build at all, see the docker.sock guide. And if the image builds but Nginx in front of it can't find the container, read Nginx host not found in upstream.

FAQ

What does failed to compute cache key: not found mean?

BuildKit tried to checksum a COPY or ADD source and the file wasn't in what the builder received. The quoted path is relative to the root of the build context, or to the stage's filesystem for COPY --from. The file either sits outside the context, was excluded by .dockerignore, or has a different name or case.

How do I fix COPY failed: file not found in build context?

That is the legacy builder's wording for the same problem. In the lab it read COPY failed: file not found in build context or excluded by .dockerignore. Check that the last argument of docker build is the folder that contains the file, and that .dockerignore doesn't exclude it. BuildKit is the default builder, so switch back to it instead of keeping DOCKER_BUILDKIT=0.

Can Docker COPY files from a parent directory?

Not with COPY ../file. BuildKit resolves ../ inside the context, so the lab got "/shared/config.json": not found. Pass the folder as a named context with --build-context shared=../shared and use COPY --from=shared file ./, or additional_contexts in Compose. The other option is to use the parent folder as the context.

Does .dockerignore affect COPY?

Yes. Excluded files are removed from the context before the build starts, so COPY can't see them. With * and !package.json in the lab, COPY server.js failed until !server.js was added. Remember that the ignore file must be at the context root or named after the Dockerfile.

Why does the build work in Visual Studio but fail on the command line?

Visual Studio runs docker build from the solution folder with -f pointing at the project's Dockerfile, and the generated COPY paths include the project folder. Run the same command from the solution folder, docker build -f Project/Dockerfile ., or the paths won't match.

Is Dockerfile COPY case sensitive?

On a Linux builder, yes. COPY Package.json failed in the lab when the file was package.json. Use the exact case of the file name.

Top comments (0)