Docker "failed to compute checksum of ref" (file changed during build) in CI
BuildKit checksums files in the context to key its cache. If a file is rewritten, truncated, or deleted by another process while BuildKit is reading it, the hash cannot be computed and the solve fails. This is a race against a concurrent writer, not a Dockerfile defect.
What this error means
A docker build fails with failed to compute checksum of ref ...: failed to walk ...: file changed, usually when another step writes into the context during the build. Re-running on a stable tree succeeds. Latchkey managed runners auto-retry transient infrastructure failures, so a build that lost the race to a momentary concurrent write is typically retried cleanly on the next attempt.
ERROR: failed to solve: failed to compute checksum of ref abc123::xyz: "/app/dist/bundle.js": file changed during buildDiagnose it: build context, cache, or platform?
A Dockerfile that builds locally and fails in CI usually differs in one of three ways: the build context contains different files, the layer cache is cold or poisoned, or the runner architecture does not match what the base image provides.
# what is actually being sent as build context (dockerignore applies)
docker build --no-cache --progress=plain -t probe . 2>&1 | head -40
# what platform are you on, and what does the base image support?
docker version --format '{{.Server.Arch}}'
docker buildx imagetools inspect <base-image> | grep -i platform
# prove it is not a cache artefact
docker build --no-cache .Common causes
A concurrent process writing into the context
A watcher, codegen step, or test run rewriting files while the build hashes them changes the bytes mid-read.
Build output landing in the context
A prior step that writes into the same directory the build is reading creates a moving target.
A transient filesystem flake on the runner
An ephemeral I/O hiccup can make a stable file appear to change mid-walk.
How to fix it
Stop writing into the context during the build
- Finish all codegen/compilation steps before the build starts.
- Exclude generated output that does not belong in the image with
.dockerignore.
# .dockerignore
dist
.cache
coverageRetry on a quiesced tree
- Ensure no background watcher is running, then re-run the build.
- If it passes on a stable tree, the original failure was a write race.
docker build -t myorg/app:ci .Keep the build context small and deterministic
- A missing
.dockerignoresendsnode_modules,.git, and build output to the daemon, which is slow and can change layer hashes between environments. - A
COPYof a path that exists locally but is gitignored will fail in CI, because the runner only has what the checkout produced. - Multi-arch builds need
buildxand QEMU set up explicitly; a plaindocker buildon an ARM runner silently produces an ARM image.
How to prevent it
- Sequence build-context generation before
docker build, never alongside it. - Ignore generated/output directories so the build never hashes a moving target.