containerd/containerd · error

failed to resolve image: %w

Error message

failed to resolve image: %w

What it means

Wraps the error from the image resolver's Resolve call at the start of a local pull. The resolver (registry referrer) could not resolve the image reference to a descriptor — the name is wrong, credentials failed, the registry is unreachable, or the manifest does not exist.

Source

Thrown at core/transfer/local/pull.go:62

	defer done(ctx)

	if tops.Progress != nil {
		tops.Progress(transfer.Progress{
			Event: fmt.Sprintf("Resolving from %s", ir),
		})
	}

	if ir, ok := ir.(transfer.ImageResolverOptionSetter); ok {
		ir.SetResolverOptions(
			transfer.WithConcurrentLayerFetchBuffer(ts.config.ConcurrentLayerFetchBuffer),
			transfer.WithMaxConcurrentDownloads(ts.config.MaxConcurrentDownloads),
			transfer.WithDownloadLimiter(ts.limiterD),
		)
	}

	name, desc, err := ir.Resolve(ctx)
	if err != nil {
		return fmt.Errorf("failed to resolve image: %w", err)
	}
	if desc.MediaType == images.MediaTypeDockerSchema1Manifest {
		// Explicitly call out schema 1 as deprecated and not supported
		return fmt.Errorf("schema 1 image manifests are no longer supported: %w", errdefs.ErrInvalidArgument)
	}

	// Verify image before pulling.
	for vfName, vf := range ts.config.Verifiers {
		logger := log.G(ctx).WithFields(log.Fields{
			"name":     name,
			"digest":   desc.Digest.String(),
			"verifier": vfName,
		})
		logger.Debug("Verifying image pull")

		jdg, err := vf.VerifyImage(ctx, name, desc)
		if err != nil {
			logger.WithError(err).Error("No judgement received from verifier")

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Verify the image reference exists: run `ctr image pull <ref>` or `docker manifest inspect <ref>`
  2. Check registry credentials/hosts.toml configuration for the mirror/host
  3. Test network reachability and TLS to the registry (curl the /v2/ endpoint)
  4. If resolution is transient (network flake), retry the transfer

Example fix

// before
err := ts.Transfer(ctx, pull.NewPuller("registry.example.com/img:lates"), ...)
// after
err := ts.Transfer(ctx, pull.NewPuller("registry.example.com/img:latest"), ...) // fix tag typo
Defensive patterns

Strategy: retry

Validate before calling

// pre-check the reference resolves before transfer
rc, err := remote.Get(resolver, ref)
if err != nil { /* reference or registry problem */ }

Try / catch

err := ts.Transfer(ctx, puller, dest, cfg)
if err != nil && strings.Contains(err.Error(), "failed to resolve image") {
    if netErr := (net.Error)(nil); errors.As(err, &netErr) { /* transient: retry with backoff */ }
    // else: fix reference/credentials
}

Prevention

When it happens

Trigger: Calling Transfer with a pull source whose reference cannot be resolved: nonexistent tag/digest, unauthorized access to a private registry, DNS/network failure to the registry, or TLS misconfiguration.

Common situations: Typo'd or non-existent image tag, pulling from a private registry without configured credentials (~/.docker/config.json or containerd hosts.toml), corporate proxy blocking the registry, expired token, or offline environment.

Related errors


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