The ProblemWe’ve all been there. You run a standard docker pull, and instead of a progress bar, you get hit with a 'manifest unknown' error. This usually happens when the Docker daemon finds the repository but cannot locate the specific version you requested. It is frustrating because the error message is vague, often leaving you wondering if the image even exists.
Error response from daemon: manifest for <image>:<tag> not found: manifest unknown: manifest unknown
Why This HappensThis error essentially means there is a disconnect between your request and what the registry has on its shelves. Here are the most frequent culprits:
- Typographical Errors: A single misplaced hyphen or a lowercase letter where an uppercase should be will break the request.- The 'latest' Trap: Docker defaults to
:latest if you don't specify a tag. However, many modern CI/CD pipelines only tag images with version numbers like v1.2.0 or Git commit SHAs, leaving the latest slot empty.- Architecture Mismatches: You might be on an M2 Mac trying to pull an image that only supports amd64. If the registry doesn't have a manifest for your specific hardware, it may return this error.- Registry Sync Issues: Private registries like Harbor or Nexus sometimes suffer from metadata corruption or interrupted pushes, leading to 'ghost' images that appear to exist but lack a valid manifest.## How to Fix It### 1. Verify the Tag ExistsNever assume a tag exists just because the repository does. Check the registry's UI first. For public images, visit Docker Hub and search for your image under the 'Tags' tab.
If you prefer the command line, you can query the registry API directly. For example, to see tags for the official Python image:
curl -L -s 'https://registry.hub.docker.com/v2/repositories/library/python/tags?page_size=5' | jq '."results"[].name'
2. Watch Your CasingDocker tags are strictly case-sensitive. While my-image:Beta and my-image:beta look the same to a human, the Docker daemon treats them as entirely different entities. Ensure your pull command matches the registry's casing exactly.
3. Specify a Version Instead of 'latest'Relying on the default tag is a common pitfall. If your team uses semantic versioning, try pulling a specific version. For instance, instead of docker pull node, try a specific, stable version:
docker pull node:20.11-bookworm-slim
4. Force the Platform ArchitectureWith the rise of Apple Silicon (M1/M2/M3) and ARM-based cloud servers, architecture mismatches are rampant. If you are on a Mac and the image was only built for Intel/AMD64 servers, Docker might fail to find a matching manifest. You can often bypass this by forcing the platform:
docker pull --platform linux/amd64 mysql:8.0
5. Use Skopeo for Deep InspectionWhen the Docker CLI isn't giving you enough information, skopeo is the professional's choice. It allows you to inspect remote images without downloading the entire 500MB+ file. It shows you exactly which architectures and tags are available.
# Install via: brew install skopeo or sudo apt install skopeo
skopeo inspect docker://docker.io/library/nginx:latest
6. Troubleshoot Private Registries (ECR/Harbor/Nexus)If you are working within a corporate environment, the issue might be permissions or sync-related. On AWS ECR, verify that your IAM policy includes ecr:BatchGetImage. For Harbor or Nexus, a 'Garbage Collection' task might have cleared a manifest index while an image was being pushed. In these cases, the most reliable fix is often to rebuild and re-push the image:
docker build -t private-reg.com/app:v1.0.5 .
docker push private-reg.com/app:v1.0.5
VerificationA successful fix results in a clean pull. You should see the digest hash and the 'Downloaded newer image' status:
$ docker pull alpine:3.19
3.19: Pulling from library/alpine
Digest: sha256:c5b1261d...
Status: Downloaded newer image for alpine:3.19
Pro-Tips for Your Workflow- Pin your versions: Stop using :latest in your Dockerfiles. It makes builds unpredictable and leads to these manifest errors.- Automate 'latest' tagging: If you want :latest to work, update your CI/CD pipeline (GitHub Actions, GitLab CI) to push two tags: the version tag and the latest tag simultaneously.- Clean local metadata: If you suspect your local Docker daemon is confused, run docker system prune to clear the cache and try again.