containerd/containerd · error

failed to get fetcher for %q: %w

Error message

failed to get fetcher for %q: %w

What it means

Wraps the error from the resolver's Fetcher method, which constructs the object used to download blobs for the resolved image. Resolution succeeded but building the fetcher (e.g. establishing a registry session/authorizer) failed.

Source

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

			return fmt.Errorf("image verifier %s blocked pull of %v with digest %v for reason: %v", vfName, name, desc.Digest.String(), jdg.Reason)
		}
		logger.Debug("Image verifier allowed pull")
	}

	// TODO: Handle already exists
	if tops.Progress != nil {
		tops.Progress(transfer.Progress{
			Event: fmt.Sprintf("Pulling from %s", ir),
		})
		tops.Progress(transfer.Progress{
			Event: "fetching image content",
			Name:  name,
			Desc:  &desc,
		})
	}
	fetcher, err := ir.Fetcher(ctx, name)
	if err != nil {
		return fmt.Errorf("failed to get fetcher for %q: %w", name, err)
	}

	var (
		handler images.Handler

		baseHandlers []images.Handler

		unpacker *unpack.Unpacker

		// has a config media type bug (distribution#1622)
		hasMediaTypeBug1622 bool

		store           = ts.content
		progressTracker *ProgressTracker
	)

	ctx, cancel := context.WithCancel(ctx)
	if tops.Progress != nil {

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Check the wrapped error and fix registry host/credential configuration (hosts.toml, auth)
  2. Re-run with registry debug logging to see which host request fails
  3. Retry in case of a transient token/session failure
  4. Validate the reference and resolver configuration match the intended registry

Example fix

// before
[host."https://mirror.local"]
  capabilities = ["pull"]   # fetcher setup fails due to bad TLS
// after
[host."https://mirror.local"]
  capabilities = ["pull"]
  ca = "/etc/containerd/certs.d/mirror.local/ca.crt"  # provide correct CA
Defensive patterns

Strategy: retry

Validate before calling

// validate hosts.toml and auth for the registry before transfer
u, _ := url.Parse("https://" + registryHost)
c, err := (&http.Client{}).Get(u.String() + "/v2/")
if err != nil || c.StatusCode >= 500 { return errors.New("registry unreachable") }

Try / catch

err := ts.Transfer(ctx, puller, dest, cfg)
if err != nil && strings.Contains(err.Error(), "failed to get fetcher") {
    // refresh credentials/session then retry with backoff
}

Prevention

When it happens

Trigger: ir.Fetcher(ctx, name) fails after a successful Resolve: usually authentication/authorization setup errors for the registry, invalid host configuration in the resolver, or an unsupported scheme.

Common situations: Registry credentials expired between resolve and fetch; hosts.toml misconfiguration (bad mirror URL/scheme); resolver configured for a host the client cannot construct a fetcher for.

Related errors


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