containerd/containerd · error

failed to get image spec: %w

Error message

failed to get image spec: %w

What it means

Start calls pauseImage.Spec(ctx) to read the image's OCI spec from the containerd image metadata. If containerd cannot resolve the image's spec — typically because the image record exists but its manifest/config blobs are missing or unreadable — this wrapped error is returned and the sandbox is not started.

Source

Thrown at internal/cri/server/podsandbox/sandbox_run.go:93

	var (
		config = metadata.Config
		labels = map[string]string{}
	)

	sandboxImage := c.getSandboxImageName()
	normalized, err := dockerref.ParseDockerRef(sandboxImage)
	if err != nil {
		return cin, fmt.Errorf("failed to parse image reference %q: %w", sandboxImage, err)
	}
	pauseImage, err := c.client.GetImage(ctx, normalized.String())
	if err != nil {
		return cin, fmt.Errorf("failed to get sandbox image %q: %w", normalized.String(), err)
	}

	// Get the image spec from containerd image
	imageSpec, err := pauseImage.Spec(ctx)
	if err != nil {
		return cin, fmt.Errorf("failed to get image spec: %w", err)
	}

	ociRuntime, err := c.config.GetSandboxRuntime(config, metadata.RuntimeHandler)
	if err != nil {
		return cin, fmt.Errorf("failed to get sandbox runtime: %w", err)
	}
	log.G(ctx).WithField("podsandboxid", id).Debugf("use OCI runtime %+v", ociRuntime)

	labels["oci_runtime_type"] = ociRuntime.Type

	// Create sandbox container root directories.
	sandboxRootDir := c.getSandboxRootDir(id)
	if err := c.os.MkdirAll(sandboxRootDir, 0755); err != nil {
		return cin, fmt.Errorf("failed to create sandbox root directory %q: %w",
			sandboxRootDir, err)
	}
	defer func() {
		if retErr != nil && cleanupErr == nil {

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Re-pull the pause image to restore missing blobs: `crictl pull <sandbox-image>`
  2. Check the content store for missing blobs (`ctr content ls`) and repair by re-pulling
  3. Ensure no GC/pruning job removes the pause image while sandboxes start
  4. Verify disk health — disk-full or I/O errors can leave partial image records
  5. If corruption persists, restart containerd; in severe cases re-pull all required images after cleanup

Example fix

// caller-side: verify the spec is readable before use
imageSpec, err := pauseImage.Spec(ctx)
if err != nil {
    // blob/manifest missing — re-pull and retry once
    if _, perr := c.client.Pull(ctx, normalized.String(), containerd.WithPullUnpack); perr != nil {
        return cin, fmt.Errorf("failed to get image spec: %w", err)
    }
    pauseImage, perr = c.client.GetImage(ctx, normalized.String())
    if perr != nil {
        return cin, fmt.Errorf("failed to get image spec: %w", perr)
    }
    imageSpec, err = pauseImage.Spec(ctx)
    if err != nil {
        return cin, fmt.Errorf("failed to get image spec: %w", err)
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// Go: verify the image spec is readable before starting sandboxes
img, err := client.GetImage(ctx, pauseRef)
if err == nil {
    if _, err := img.Spec(ctx); err != nil {
        // blobs missing — re-pull to repair the content store
        _, _ = client.Pull(ctx, pauseRef, containerd.WithPullUnpack)
    }
}

Try / catch

imageSpec, err := pauseImage.Spec(ctx)
if err != nil {
    // repair by re-pulling, then retry once
    if _, perr := c.client.Pull(ctx, normalized.String(), containerd.WithPullUnpack); perr == nil {
        if img, gerr := c.client.GetImage(ctx, normalized.String()); gerr == nil {
            imageSpec, err = img.Spec(ctx)
        }
    }
    if err != nil {
        return cin, fmt.Errorf("failed to get image spec: %w", err)
    }
}

Prevention

When it happens

Trigger: The pause image was pulled but its blobs were deleted by aggressive GC, the image was pulled on a different snapshotter/content store, or the containerd content store is corrupted.

Common situations: Content-store corruption after a crash or disk-full event; pruning jobs (e.g. crictl rmi --prune) racing with sandbox creation; mixed containerd versions where image metadata formats differ; running Start concurrently with an image deletion.

Related errors


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