Docker "target stage could not be found" - Fix Multi-Stage Builds
You asked BuildKit to build (or copy from) a named stage that the Dockerfile does not define. The stage name in the command and the AS <name> in the file disagree.
What this error means
A build with --target <name>, or a COPY --from=<name>, fails with target stage "<name>" could not be found. The Dockerfile builds fine without the target.
ERROR: failed to solve: target stage "prod" could not be found
# Dockerfile defines: FROM nginx AS production (not "prod")Diagnose 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
Typo or mismatch in the stage name
The --target/--from value does not exactly match a FROM ... AS <name> in the Dockerfile (e.g. prod vs production).
The stage is not defined in this Dockerfile
You referenced a stage that exists in a different Dockerfile, or was renamed/removed, so it is absent from the one being built.
How to fix it
Match the target to a defined stage
Name stages explicitly and reference them by the exact same name.
FROM node:20 AS build
# ...
FROM nginx:alpine AS production
# build it:
docker build --target production -t api .List the stages in the Dockerfile
Grep the stage names so the target is unambiguous.
grep -niE '^FROM .* AS ' DockerfileKeep 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
- Keep stage names consistent between the Dockerfile and CI commands.
- Reference stage names from a single variable where possible.
- Lint for COPY --from references that name a non-existent stage.