Skip to content
Latchkey

Docker "invalid reference format" - Fix Bad Image Names in CI

Docker rejected the image reference before contacting any registry because it does not match the grammar for a valid name and tag.

What this error means

A docker build -t, docker tag, docker pull, or docker run fails instantly with invalid reference format, sometimes adding repository name must be lowercase. No network call is made.

Terminal
docker: invalid reference format: repository name must be lowercase.
# e.g. from: docker build -t MyOrg/API:Latest .  or an empty ${IMAGE} variable

Diagnose it: separate auth from naming from rate limits

Registry errors look alike and have unrelated causes. Work out which of the three you have before changing credentials, because a malformed image reference produces an error that reads like an authentication failure.

Terminal
# 1. is the reference even valid? (lowercase, no spaces, valid tag)
docker image inspect "$IMAGE" 2>&1 | head -2

# 2. are you authenticated to the right registry?
cat ~/.docker/config.json | grep -o '"[^"]*\.[^"]*"' | head

# 3. are you rate limited? (Docker Hub anonymous pulls)
curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimit-preview/test:pull" \
  | grep -o '"token"' >/dev/null && echo "token ok"

Common causes

Uppercase letters or illegal characters

Repository names must be lowercase and may only contain a restricted character set. MyOrg/API, spaces, or stray characters break the grammar.

An unsubstituted or empty variable

A reference like ${REGISTRY}/api:${TAG} where a variable is empty collapses to something malformed (/api: or :latest with a leading colon), which Docker cannot parse.

Malformed digest or double separators

A bad @sha256: digest, a double slash, or a trailing colon produces a reference that fails validation.

How to fix it

Lowercase the name and remove illegal characters

Normalize the repository name; lowercase any branch or org value interpolated into it.

Terminal
IMAGE="ghcr.io/${OWNER,,}/api:${TAG}"   # bash lowercases OWNER
docker build -t "$IMAGE" .

Echo the reference before using it

Print the fully-expanded reference so an empty variable is obvious.

Terminal
echo "building: ${REGISTRY}/api:${TAG}"
test -n "${TAG}" || { echo "TAG is empty"; exit 1; }

Authenticate in the job, not in the image

.github/workflows/ci.yml
- uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}

# GHCR needs this on the job or the push is rejected as unauthorised
permissions:
  contents: read
  packages: write

How to prevent it

  • Lowercase any dynamic org/branch values before putting them in an image name.
  • Default tag variables and assert they are non-empty before building.
  • Keep image references in one place so the grammar is easy to audit.

Frequently asked questions

What causes Docker "invalid reference format"?
There are 3 common causes: uppercase letters or illegal characters, an unsubstituted or empty variable, and malformed digest or double separators. Repository names must be lowercase and may only contain a restricted character set.
How do I fix Docker "invalid reference format"?
There are 2 fixes depending on which cause you have: lowercase the name and remove illegal characters and echo the reference before using it. Work through them in order, since the first is the most common.
What does Docker "invalid reference format" actually mean?
A docker build -t, docker tag, docker pull, or docker run fails instantly with invalid reference format, sometimes adding repository name must be lowercase.
How do I stop Docker "invalid reference format" happening again?
Lowercase any dynamic org/branch values before putting them in an image name. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

This is a registry failure, not a bug in your code. Latchkey detects, repairs, and retries it for you. Start free → 30-day trial · No credit card