Skip to content
DevOps AI ToolKit
Newsletter
All guides
Docker with AI By James Joyner IV · · 9 min read

Docker Error Guide: 'manifest unknown' Missing Tag or Digest

Fix Docker 'manifest for <image>:<tag> not found: manifest unknown': use a tag that exists, push the missing tag, check digests, and inspect the registry with manifest inspect.

  • #docker
  • #troubleshooting
  • #errors
  • #registry

Exact Error Message

When the repository is reachable but the requested tag or digest is not in it, the daemon returns:

Error response from daemon: manifest for myorg/api:v2.3.1 not found: manifest unknown: manifest unknown

You may also see the shorter registry form on a digest pull:

Error response from daemon: manifest unknown: OCI index found, but no matching manifest found for platform

The key word is manifest. Unlike pull access denied, this error means the registry authorized you and successfully resolved the repository — it just has no manifest stored under the tag or digest you asked for.

This shows up on docker pull, on docker run, in a FROM line during docker build, and in docker compose pulls. It is one of the most common deploy-time surprises: the repository and your credentials are both fine, so engineers waste time re-checking docker login when the real problem is a single wrong character in a tag, or a latest that was never published.

What It Means

A container image reference is repository:tag or repository@sha256:digest. The registry stores a manifest (a small JSON document listing the layers and config) for every tag and digest. When you pull, the daemon first fetches that manifest. manifest unknown is the registry saying: “I found the repository, I let you read it, but there is nothing stored under that tag/digest.” This is a successful, authorized lookup that returned empty — fundamentally different from an auth failure or a network error. No layers are attempted because there is no manifest to read them from.

Common Causes

  • The tag never existed. A typo (v2.3.1 vs v2.3.0), or a tag that was planned but never pushed.
  • :latest is absent. You ran docker pull myorg/api (which defaults to :latest), but the repo only has versioned tags and no latest.
  • The tag was deleted or overwritten. A retention/GC policy pruned it, or a re-tag moved it elsewhere.
  • A pinned digest was removed. You pin @sha256:... but the underlying image was garbage-collected, so the digest no longer resolves.
  • Registry mirror or replication lag. The tag exists on the primary but has not yet propagated to the mirror or pull-through cache you are hitting.
  • Wrong registry. The tag exists on ghcr.io/myorg/api but you are pulling the Docker Hub myorg/api, which has different tags.
  • Case or format mismatch. Some registries are case-sensitive on tags, and a v1.0 vs 1.0 or V1.0 discrepancy resolves to a different (absent) manifest.
  • CI race condition. A deploy job referenced the tag before the build/push job finished publishing it, so the manifest legitimately did not exist yet at pull time.

How to Reproduce the Error

Pull a tag that does not exist on an image you can otherwise read:

docker pull myorg/api:does-not-exist
Error response from daemon: manifest for myorg/api:does-not-exist not found: manifest unknown: manifest unknown

Diagnostic Commands

First confirm whether the tag exists at all. docker manifest inspect queries the registry directly using your stored credentials:

docker manifest inspect myorg/api:v2.3.1
no such manifest: docker.io/myorg/api:v2.3.1

List the tags that actually exist. docker has no native “list tags,” so use the registry API, crane, or skopeo:

crane ls myorg/api
skopeo list-tags docker://docker.io/myorg/api
v2.2.0
v2.3.0
latest

For OCI-aware registries, docker buildx imagetools inspect shows the manifest list and its referenced manifests:

docker buildx imagetools inspect myorg/api:v2.3.0

You can also query the registry HTTP API directly when CLI tooling is unavailable. The /v2/<repo>/tags/list endpoint returns every tag; a missing tag here is definitive:

TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:myorg/api:pull" | jq -r .token)
curl -s -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/myorg/api/tags/list
{"name":"myorg/api","tags":["v2.2.0","v2.3.0","latest"]}

If you are chasing a pinned digest, confirm the digest still resolves:

docker manifest inspect myorg/api@sha256:abc123...
journalctl -u docker --since "5 min ago" | grep -i 'manifest'

A manifest unknown from docker manifest inspect on a tag you believe was pushed points at registry lag or a wrong registry host — compare against docker info | grep -i registry.

Step-by-Step Resolution

Cause: typo or wrong tag. Use a tag from the crane ls/skopeo list-tags output. Correct the reference in your compose file, docker run, or manifest, then re-pull:

docker pull myorg/api:v2.3.0

Cause: :latest not published. Either pull an explicit version tag, or have your build push a latest tag alongside the version:

docker tag myorg/api:v2.3.0 myorg/api:latest
docker push myorg/api:latest

Cause: tag was never pushed. Build and push it. Confirm the push reported a digest and the tag now appears in crane ls:

docker build -t myorg/api:v2.3.1 .
docker push myorg/api:v2.3.1
crane ls myorg/api | grep v2.3.1

Cause: pinned digest removed. Stop pinning a garbage-collected digest. Re-resolve the current digest for the tag you want and re-pin:

docker buildx imagetools inspect myorg/api:v2.3.0 --format '{{.Manifest.Digest}}'

Cause: mirror/replication lag. Wait for propagation, or pull from the primary registry host directly. If you run a pull-through cache, check its sync logs.

Cause: wrong registry. Add the correct host to the reference (ghcr.io/myorg/api:v2.3.1) and confirm docker info is not pointing the daemon at an unexpected mirror.

A short worked example ties it together. A CI deploy fails with manifest for myorg/api:2024.06.1 not found: manifest unknown. Auth is clearly fine because docker manifest inspect myorg/api:latest succeeds. Listing tags reveals the published tag is v2024.06.1 (with a v prefix) — the deploy template dropped the prefix:

crane ls myorg/api | grep 2024.06
v2024.06.0
v2024.06.1

Correcting the reference to myorg/api:v2024.06.1 resolves the pull immediately; no credential change was needed. The lesson is to read manifest unknown as a tag/digest problem first and only fall back to auth and network if the tag provably exists.

How to Prevent the Issue

  • Verify the tag exists in the registry in CI (e.g. crane manifest <repo>:<tag>) before any deploy references it.
  • Prefer immutable, versioned tags over latest, and publish latest explicitly if your tooling expects it.
  • Treat tags as immutable in the registry (enable tag immutability) so a re-tag cannot pull a digest out from under a deploy.
  • Pin by digest only when you also retain those images; align GC/retention policies with what is still referenced.
  • Monitor mirror/replication lag so consumers do not race ahead of propagation.
Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.