GitLab CI image pull failed - private registry or missing image
Job fails with 'Error response from daemon: manifest for <image> not found'
Focused incident mode — strips away everything but this runbook.
Symptoms
- Job fails with 'Error response from daemon: manifest for <image> not found'
- GitLab CI job log shows 'pulling image failed' or 'unauthorized'
- Job stays in pending with 'Preparing environment' then fails on image pull
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Image specified in .gitlab-ci.yml
grep -E '^\s*image:' .gitlab-ci.yml | head -5Docker registry credentials in GitLab
glab api /projects/<PROJECT_ID>/variables --jq '.[] | select(.key | test("REGISTRY|DOCKER")) | .key'
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- Job fails with 'unauthorized: authentication required'
- Image is in a private registry (e.g., ghcr.io, registry.gitlab.com)
- No CI/CD variable named REGISTRY_PASSWORD or DOCKER_AUTH_CONFIG
Confirm before fixing
glab api /projects/<PROJECT_ID>/variables --jq '.[] | .key'List all CI/CD variables
Fix
glab api -X POST /projects/<PROJECT_ID>/variables -f key=REGISTRY_PASSWORD -f value=<TOKEN> -f protected=true -f masked=trueAdd registry password as a protected CI variable
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
glab ci trace <PIPELINE_ID> --job <JOB_ID> | grep -E 'pulling|manifest|unauthorized' | head -10Read the image pull error
docker manifest inspect <IMAGE>:<TAG>Verify the image exists
glab api /projects/<PROJECT_ID>/variables --jq '.[] | .key'Check for registry credentials
glab api -X POST /projects/<PROJECT_ID>/variables -f key=REGISTRY_PASSWORD -f value=<TOKEN> -f masked=trueAdd missing registry credentials
Prevention
- Always pin images to a specific tag or SHA, never use :latest.
- Store registry credentials as protected, masked CI/CD variables.
- Pre-pull images on shared runners during off-peak hours.
- Use GitLab's built-in Container Registry for first-party images.
Related runbooks
Same stack, same failure family — worth a skim.
Job stuck in 'pending' state with 'Waiting for a runner'
docker push to registry.gitlab.com fails with 'unauthorized' or 401
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.