containerd/containerd · error

failed to resolve layers: %w

Error message

failed to resolve layers: %w

What it means

resolveLayers failed while mapping each layer filename in the manifest to an ingested blob descriptor and preparing content-store filters. The wrapped inner error carries the real cause (e.g. 'layer %q not found', media-type detection failures, or store walk errors). ImportIndex wraps it to attribute the failure to layer resolution for the current manifest.

Source

Thrown at core/images/archive/importer.go:172

		}
		blobs[name] = desc
	}

	idx := ocispec.Index{
		Versioned: specs.Versioned{
			SchemaVersion: 2,
		},
	}
	for _, mfst := range mfsts {
		config, ok := blobs[mfst.Config]
		if !ok {
			return ocispec.Descriptor{}, fmt.Errorf("image config %q not found", mfst.Config)
		}
		config.MediaType = images.MediaTypeDockerSchema2Config

		layers, err := resolveLayers(ctx, store, mfst.Layers, blobs, iopts.compress)
		if err != nil {
			return ocispec.Descriptor{}, fmt.Errorf("failed to resolve layers: %w", err)
		}

		manifest := struct {
			SchemaVersion int                  `json:"schemaVersion"`
			MediaType     string               `json:"mediaType"`
			Config        ocispec.Descriptor   `json:"config"`
			Layers        []ocispec.Descriptor `json:"layers"`
		}{
			SchemaVersion: 2,
			MediaType:     images.MediaTypeDockerSchema2Manifest,
			Config:        config,
			Layers:        layers,
		}

		desc, err := writeManifest(ctx, store, manifest, manifest.MediaType)
		if err != nil {
			return ocispec.Descriptor{}, fmt.Errorf("write docker manifest: %w", err)
		}

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Read the wrapped cause: if it says layer not found, fix the archive so every manifest.json Layers path exists in the tar
  2. If the cause is a store error, check containerd content store health and disk space (`ctr content ls`, df)
  3. Re-export the image with docker save or skopeo to get a clean archive
  4. Verify layer compression (gzip/zstd/none) is standard and supported
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-validate that every manifest.json Layers path exists in the tar
for _, m := range mfsts {
    for _, l := range m.Layers {
        if !contains(tarFiles, l) { return fmt.Errorf("layer %s missing", l) }
    }
}

Try / catch

if err := client.Import(ctx, reader); err != nil {
    if strings.Contains(err.Error(), "failed to resolve layers") {
        log.Errorf("layer resolution failed: %v", errors.Unwrap(err))
        // branch on the wrapped cause (missing layer vs store error)
    }
    return err
}

Prevention

When it happens

Trigger: ImportIndex calls resolveLayers(ctx, store, mfst.Layers, blobs, compress) and it returns an error: a listed layer file is absent from blobs, the content-store Walk with LabelUncompressed filters fails, or detectLayerMediaType/ReaderAt/DecompressStream errors occur inside.

Common situations: Archives with truncated layer lists after manual editing; content store out of space or corrupted causing Walk/ReaderAt failures; layers stored as symlinks with missing targets; unusual compression formats the decompressor cannot sniff.

Related errors


AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02). Data as JSON: /api/errors/91868888f7d6da75. Report an issue: GitHub.