docker/cli · error

is not a manifest

Error message

%s is not a manifest

What it means

The default branch of fetchManifest's type switch — the object returned by the registry is none of schema2 DeserializedManifest, OCI DeserializedManifest, or DeserializedManifestList. Schema 1 was explicitly removed, so this typically means an old or non-standard manifest media type the client no longer understands.

Solutions

  1. Re-build and re-push the image so it is stored as schema2 or OCI.
  2. Upgrade the registry to a current distribution release.
  3. Inspect the manifest media type with crane / skopeo / docker manifest inspect to identify what is being served.
  4. If you must read the old image, use a tool that still supports the legacy schema.

Example fix

# old image served as schema 1 -> repush with current docker build/push
docker pull legacy/img:tag && docker tag legacy/img:tag myreg/img:tag && docker push myreg/img:tag
Defensive patterns

Strategy: validation

Validate before calling

// Inspect the manifest media type before expecting fetchManifest to handle it.
var supportedSingle = map[string]bool{
    "application/vnd.docker.distribution.manifest.v2+json":      true,
    "application/vnd.oci.image.manifest.v1+json":                true,
}
// fetch the descriptor/media type via registry API, then check the map.

Prevention

When it happens

Trigger: A registry serves a v2 schema-1 manifest, an unknown media type, or a future/custom manifest type not handled by this version of docker/cli.

Common situations: Very old images pushed with deprecated schema 1; version skew between an older registry and a newer CLI that dropped schema 1; a custom registry serving non-standard manifests.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/02f489a09f6a60f1. Report an issue: GitHub.

Appendix: source

Thrown at internal/registryclient/fetcher.go:41

// fetchManifest pulls a manifest from a registry and returns it. An error
// is returned if no manifest is found matching namedRef.
func fetchManifest(ctx context.Context, repo distribution.Repository, ref reference.Named) (types.ImageManifest, error) {
	manifest, err := getManifest(ctx, repo, ref)
	if err != nil {
		return types.ImageManifest{}, err
	}

	switch v := manifest.(type) {
	// Removed Schema 1 support
	case *schema2.DeserializedManifest:
		return pullManifestSchemaV2(ctx, ref, repo, *v)
	case *ocischema.DeserializedManifest:
		return pullManifestOCISchema(ctx, ref, repo, *v)
	case *manifestlist.DeserializedManifestList:
		return types.ImageManifest{}, fmt.Errorf("%s is a manifest list", ref)
	}
	return types.ImageManifest{}, fmt.Errorf("%s is not a manifest", ref)
}

func fetchList(ctx context.Context, repo distribution.Repository, ref reference.Named) ([]types.ImageManifest, error) {
	manifest, err := getManifest(ctx, repo, ref)
	if err != nil {
		return nil, err
	}

	switch v := manifest.(type) {
	case *manifestlist.DeserializedManifestList:
		return pullManifestList(ctx, ref, repo, *v)
	default:
		return nil, fmt.Errorf("unsupported manifest format: %v", v)
	}
}

func getManifest(ctx context.Context, repo distribution.Repository, ref reference.Named) (distribution.Manifest, error) {
	manSvc, err := repo.Manifests(ctx)

View on GitHub (pinned to 4f84911bfe)