The 'failed to parse stage name' error occurs when Docker BuildKit cannot properly parse a stage name in a FROM instruction. This typically happens due to uppercase letters in stage names, undefined ARG variables, or invalid characters. The fix involves using lowercase stage names and ensuring all build arguments are properly defined.
This error indicates that Docker's build system (BuildKit) encountered a stage name it couldn't parse in your Dockerfile. The error typically appears during `docker build` operations when using multi-stage builds or ARG variables in FROM instructions. The full error message usually looks like: ``` failed to solve with frontend dockerfile.v0: failed to build LLB: failed to parse stage name "STAGENAME": invalid reference format ``` This happens because Docker's image reference parser has strict rules about what constitutes a valid name. When a stage name violates these rules - whether due to uppercase letters, missing variable values, or invalid characters - the build fails immediately before any actual building occurs. The error originates from BuildKit's LLB (Low-Level Builder) definition phase, which parses the entire Dockerfile and constructs a build graph before executing any instructions.
The most common cause is using uppercase letters in stage names. BuildKit requires lowercase stage names:
# Wrong - uppercase stage names
FROM node:20-alpine AS BUILD
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:20-alpine AS RUNTIME
COPY --from=BUILD /app/node_modules ./node_modules
# Correct - lowercase stage names
FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:20-alpine AS runtime
COPY --from=build /app/node_modules ./node_modulesThis is especially important when referencing stages with COPY --from= or FROM instructions.
When using variables in FROM instructions, the ARG must be declared before the first FROM statement:
# Wrong - ARG after FROM
FROM node:${NODE_VERSION}-alpine
ARG NODE_VERSION=20
# Correct - ARG before FROM
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpineIf you need the variable available in build stages, redeclare it after FROM (ARG values don't persist across stages):
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine AS build
ARG NODE_VERSION # Re-declare to use in this stage
RUN echo "Building with Node ${NODE_VERSION}"Ensure build arguments are passed to the docker build command:
# Check if the ARG has a default value
# If not, you must pass it at build time
# Wrong - missing required argument
docker build -t myapp .
# Correct - passing the argument
docker build --build-arg NODE_VERSION=20 -t myapp .
# Or set a default in Dockerfile
ARG NODE_VERSION=20 # Default value if not provided
FROM node:${NODE_VERSION}-alpineIn docker-compose.yml:
services:
app:
build:
context: .
args:
NODE_VERSION: "20"An empty ARG results in an invalid image reference like node::
# Debug: Check what value is being used
docker build --build-arg NODE_VERSION=20 -t myapp . --progress=plain
# In CI, verify environment variables are set
echo "NODE_VERSION=${NODE_VERSION}"Common issues in CI/CD:
# GitHub Actions - variable might be empty
- name: Build
run: |
# Verify the variable exists
if [ -z "${{ env.VERSION }}" ]; then
echo "VERSION is not set!"
exit 1
fi
docker build --build-arg VERSION=${{ env.VERSION }} -t app .Stage names must follow specific rules:
- Start with a lowercase letter
- Contain only lowercase letters, digits, and separators (., -, _)
- Not contain uppercase letters or special symbols
# Invalid stage names
FROM alpine AS 1stStage # Cannot start with number
FROM alpine AS my-Stage # Contains uppercase
FROM alpine AS my@stage # Contains invalid symbol
FROM alpine AS MY_BUILD # All uppercase
# Valid stage names
FROM alpine AS stage1
FROM alpine AS my-stage
FROM alpine AS my_stage
FROM alpine AS build.dev
FROM alpine AS baseImage references can only have one colon. A common mistake is adding :latest to an already-tagged image:
# Wrong - two colons
FROM node:20-alpine:latest
# Correct - single colon
FROM node:20-alpine
# or
FROM node:latestThis can happen when concatenating variables:
# Wrong - if TAG already contains a colon
ARG TAG=20-alpine
FROM node:${TAG}:latest # Results in node:20-alpine:latest
# Correct
ARG TAG=20-alpine
FROM node:${TAG}Windows line endings (CRLF) can cause parsing issues:
# Check for Windows line endings
file Dockerfile
# If it shows "with CRLF line terminators", convert it:
# Using sed
sed -i 's/\r$//' Dockerfile
# Using dos2unix
dos2unix Dockerfile
# In VS Code: Click "CRLF" in status bar and select "LF"In Git, configure automatic conversion:
# .gitattributes
Dockerfile text eol=lf
*.sh text eol=lfDocker Compose v2 may handle ARG values differently:
# docker-compose.yml
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
# Explicitly set all ARGs
NODE_VERSION: "20"
# Or reference environment variables
BUILD_ENV: ${BUILD_ENV:-production}If using environment files:
# .env file
NODE_VERSION=20
# Verify variables are loaded
docker compose configNote: docker-compose (v1) and docker compose (v2) may behave differently. Try both if one fails.
### Understanding BuildKit and LLB
Docker BuildKit uses LLB (Low-Level Builder) as an intermediate representation. When you run docker build, BuildKit:
1. Parses the Dockerfile into an LLB definition
2. Validates all references (including stage names)
3. Constructs a dependency graph
4. Executes the build
The "failed to parse stage name" error occurs at step 2, before any actual building. This is why the error appears immediately without any layer building.
### BuildKit vs Legacy Builder
The legacy builder (pre-BuildKit) was more lenient with stage names. When Docker Desktop or newer Docker versions default to BuildKit, previously working Dockerfiles may fail:
# Temporarily disable BuildKit (not recommended for production)
DOCKER_BUILDKIT=0 docker build -t myapp .
# Check current BuildKit status
docker buildx versionHowever, rather than disabling BuildKit, fix the Dockerfile to comply with its stricter requirements.
### Multi-stage Build Best Practices
# Use descriptive lowercase stage names
ARG GO_VERSION=1.21
FROM golang:${GO_VERSION}-alpine AS deps
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
FROM deps AS build
COPY . .
RUN go build -o /app/server .
FROM alpine:3.18 AS runtime
COPY --from=build /app/server /usr/local/bin/
ENTRYPOINT ["server"]### Debugging Stage Name Issues
# Parse Dockerfile without building
docker buildx build --print .
# Build with verbose output
docker build --progress=plain -t myapp .
# Check what variables are being used
docker build --build-arg NODE_VERSION=20 -t myapp . 2>&1 | head -20### CI/CD Considerations
In CI environments, ensure ARG values are explicitly passed:
# GitHub Actions
- name: Build Docker image
run: |
docker build \
--build-arg NODE_VERSION=${{ matrix.node-version }} \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
-t myapp:${{ github.sha }} \
.
# GitLab CI
build:
script:
- docker build
--build-arg CI_COMMIT_SHA=$CI_COMMIT_SHA
--build-arg NODE_VERSION=${NODE_VERSION:-20}
-t $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG .image operating system "linux" cannot be used on this platform
How to fix 'image operating system linux cannot be used on this platform' in Docker
manifest unknown: manifest unknown
How to fix 'manifest unknown' in Docker
cannot open '/etc/passwd': Permission denied
How to fix 'cannot open: Permission denied' in Docker
Error response from daemon: failed to create the ipvlan port
How to fix 'failed to create the ipvlan port' in Docker
toomanyrequests: Rate exceeded for anonymous users
How to fix 'Rate exceeded for anonymous users' in Docker Hub