Overview
“Error response from daemon: invalid reference format” means Docker parsed an image reference (repository[:tag] or @digest) that does not match the required syntax. This appears in commands like docker run, pull, build -t, tag, push, and even in Dockerfiles (FROM lines) or Compose files.
This guide shows practical, fast fixes.
Quickstart: Fix it fast
- Remove protocols and whitespace
- Wrong: docker pull https://gcr.io/myproj/app:1.0
- Right: docker pull gcr.io/myproj/app:1.0
- Trim stray spaces and quotes around image names.
- Use valid name syntax
- Repositories: lowercase only, [a-z0-9_.-], slash-separated.
- Tags: up to 128 chars, [A-Za-z0-9_.-].
- Don’t mix tag and digest together.
- Keep -t and build context separate
- Right: docker build -t myorg/app:1.0 .
- Wrong: docker build -t myorg/app:1.0.
- Check env vars
- Ensure $IMAGE is set and non-empty. Provide defaults: ${IMAGE:-alpine:3.20}.
- For Dockerfiles/Compose
- Dockerfile FROM must resolve to a valid image.
- Compose image: must be a valid reference without protocols.
Minimal working example
A minimal, correct build and run to compare against your command.
Dockerfile:
FROM alpine:3.20
CMD ["echo", "ok"]
Build and run:
# Build with a valid, lowercase repository and a simple tag
docker build -t myorg/echo:1.0 .
# Run using the exact image:tag reference
docker run --rm myorg/echo:1.0
# output: ok
If the above works on your machine, your Docker setup is fine; your failing command likely has a malformed image reference.
Valid image reference syntax
- Full form: [registryhost[:port]/]repo[/subrepo][:tag] or [registryhost[:port]/]repo[/subrepo]@sha256:<digest>
- repo and subrepos: lowercase only; allowed chars: a–z, 0–9, ., _, -
- tag (optional): 1–128 chars; allowed: A–Z, a–z, 0–9, ., _, -
- digest (optional): sha256:<64-hex>; cannot be combined with :tag
Examples:
- Valid: nginx, nginx:1.27.0, myregistry:5000/team/app:2025-10-06, gcr.io/proj/svc@sha256:...
- Invalid: Nginx:latest (uppercase repo), https://gcr.io/app (protocol), repo/image:tag:extra (extra colon), image:@sha256:... (empty tag before @)
Common causes and fixes
| Symptom | Bad | Why | Fix |
|---|---|---|---|
| Protocol in image | docker pull https://gcr.io/proj/app:1 | Protocol not allowed | docker pull gcr.io/proj/app:1 |
| Uppercase repo | docker run MyOrg/App:1 | Repo must be lowercase | docker run myorg/app:1 |
| Extra colon in tag | repo/app:1:2 | Multiple tag separators | repo/app:1-2 or repo/app:1 |
| Tag + digest together | app:1@sha256:abc... | Spec forbids both | app@sha256:abc... or app:1 |
| Trailing space/quote | docker pull "nginx:latest " | Space makes tag invalid | docker pull nginx:latest |
| Missing space before context | docker build -t app:1.0. | CLI treats “1.0.” as tag | docker build -t app:1.0 . |
| Empty env var | docker run "$IMAGE" | IMAGE expands to empty | docker run "${IMAGE:-alpine:3.20}" |
| Compose with protocol | image: https://index.docker.io/nginx | Invalid reference | image: nginx:latest |
| Dockerfile FROM undefined ARG | FROM ${BASE_IMAGE} | BASE_IMAGE empty at build time | ARG BASE_IMAGE=alpine:3.20 then FROM ${BASE_IMAGE} |
Step-by-step diagnosis
- Identify exactly which reference failed
- Re-run with -D for Docker CLI debug: DOCKER_CLI_HINTS=false docker -D run ...
- If using Compose: docker compose config to see resolved image values.
- Echo your variables
- Print: echo "IMAGE='$IMAGE'"; ensure not empty, no newline/spaces.
- Bash default: IMAGE="${IMAGE:-myorg/app:1.0}".
- Validate with a quick regex (approximation)
ref='gcr.io/team/app:1.0'
[[ $ref =~ ^([a-z0-9]+([._-][a-z0-9]+)*(:[0-9]+)?/)?([a-z0-9]+([._-][a-z0-9]+)*/)*[a-z0-9]+([._-][a-z0-9]+)*(:([-A-Za-z0-9._]+))?$|^([a-z0-9]+([._-][a-z0-9]+)*(:[0-9]+)?/)?([a-z0-9]+([._-][a-z0-9]+)*/)*[a-z0-9]+([._-][a-z0-9]+)*@sha256:[0-9a-f]{64}$ ]] && echo OK || echo BAD
- Test locally without network
- docker image inspect <ref> 1>/dev/null 2>&1 || echo "Not local yet, but format may still be OK"
- If inspect fails with “invalid reference format”, your string is malformed.
- Common command fixes
- build: docker build -t myorg/app:1.0 .
- run: docker run --rm myregistry:5000/myorg/app:1.0
- pull: docker pull registry.local:5000/team/app:2025.10.06
- tag: docker tag app@sha256:... registry.local:5000/app:stable
Dockerfile and Compose specifics
Dockerfile FROM
- If using ARG: add a default and pass when building.
ARG BASE_IMAGE=alpine:3.20 FROM ${BASE_IMAGE}- Build: docker build --build-arg BASE_IMAGE=alpine:3.20 -t my/app:1 .
docker-compose.yml
services: web: image: nginx:1.27.0- With env default: image: ${IMAGE:-nginx:1.27.0}
- Avoid protocols and trailing spaces in the image value.
Pitfalls to avoid
- Mixing port mappings and image names without a space: always separate flags from the image argument.
- Copy-pasting registry URLs with https:// or trailing slashes.
- Using uppercase letters in repository components.
- Accidentally appending the build context dot to the tag (…:tag.).
- Combining :tag with @sha256:digest.
- Hidden characters from editors (non-breaking spaces, newlines). Run: printf '%q\n' "$IMAGE".
Performance notes
- Format errors are caught client-side; fixing the string avoids unnecessary network calls.
- Validate references before loops or CI matrix runs to save pull time.
- Prefer immutable digests (app@sha256:...) in CI for reproducible, cache-friendly builds; just don’t pair them with tags.
- Use local inspect to short-circuit: docker image inspect <ref> is fast and avoids registry hits if the image exists locally.
FAQ
What does “invalid reference format” actually mean?
- The image name/tag/digest string does not match Docker’s expected grammar.
Can repository names contain uppercase letters?
- No. Keep repository and path components lowercase. Tags may include uppercase, but lowercase is safest.
Can I include a protocol like https:// in the image?
- No. Use registryhost[:port]/repo[:tag] without a scheme.
Why do I see this in a Dockerfile FROM line?
- The expanded value (often from ARG) produced an invalid or empty image reference.
How do I safely use env vars for images?
- Provide defaults and trim whitespace: IMAGE="${IMAGE:-alpine:3.20}"; then reference "$IMAGE" in commands.