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
- Re-pull the pause image to restore missing blobs: `crictl pull <sandbox-image>`
- Check the content store for missing blobs (`ctr content ls`) and repair by re-pulling
- Ensure no GC/pruning job removes the pause image while sandboxes start
- Verify disk health — disk-full or I/O errors can leave partial image records
- 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
- Stop aggressive prune jobs (crictl rmi --prune) from removing pause image blobs
- Re-pull images after disk-full or crash events to repair partial content records
- Monitor containerd content-store health and available disk space
- Verify image integrity with `ctr images check` when specs start failing
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
- failed to generate image info: %w
- writer has been reset
- unable to discard to offset
- `mirrors` cannot be set when `config_path` is provided
- `default_runtime_name` is empty
AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02).
Data as JSON: /api/errors/be0c866125d0c449.
Report an issue: GitHub.