juanfont/headscale · error

pulling image %s: %w

Error message

pulling image %s: %w

What it means

Returned inside `ensureImageAvailable`'s retry closure when `cli.ImagePull` itself errors and the error is not classified as permanent (`isPermanentDockerPullError`). It is retried with exponential backoff up to 60s total; if backoff is exhausted the error surfaces. Permanent errors (e.g. repository not found, auth failure) abort immediately via backoff.Permanent.

Source

Thrown at cmd/hi/docker.go:560

	if verbose {
		log.Printf("Image %s not found locally, pulling...", imageName)
	}

	registryAuth, err := dockertestutil.RegistryAuth()
	if err != nil {
		return fmt.Errorf("resolving registry auth: %w", err)
	}

	_, err = backoff.Retry(
		ctx,
		func() (struct{}, error) {
			reader, pullErr := cli.ImagePull(ctx, imageName, image.PullOptions{RegistryAuth: registryAuth})
			if pullErr != nil {
				if isPermanentDockerPullError(pullErr) {
					return struct{}{}, backoff.Permanent(pullErr)
				}

				return struct{}{}, fmt.Errorf("pulling image %s: %w", imageName, pullErr)
			}
			defer reader.Close()

			sink := io.Discard
			if verbose {
				sink = os.Stdout
			}

			_, copyErr := io.Copy(sink, reader)
			if copyErr != nil {
				return struct{}{}, fmt.Errorf("reading pull output: %w", copyErr)
			}

			return struct{}{}, nil
		},
		backoff.WithBackOff(backoff.NewExponentialBackOff()),
		backoff.WithMaxElapsedTime(60*time.Second),
	)

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Manually pull to see the real error: `docker pull golang:<version>`.
  2. If rate-limited: `docker login` or configure registry mirrors; consider retagging a locally cached image.
  3. Verify the tag exists on Docker Hub for the configured GoVersion.
  4. For persistent network issues, fix proxy/DNS, then re-run — retry budget is only 60s.
Defensive patterns

Strategy: retry

Validate before calling

// verify the tag exists before configuring the run
if err := exec.Command("docker", "manifest", "inspect", "golang:"+cfg.GoVersion).Run(); err != nil {
    return fmt.Errorf("golang:%s is not a published tag: %w", cfg.GoVersion, err)
}

Try / catch

err := ensureImageAvailable(ctx, cli, image, verbose)
if err != nil && strings.Contains(err.Error(), "pulling image") {
    if strings.Contains(err.Error(), "toomanyrequests") {
        // rate limited: docker login or mirror, then retry
    } else if strings.Contains(err.Error(), "not found") {
        // permanent: fix the tag; do not retry
    }
}

Prevention

When it happens

Trigger: Transient network failures to the registry; Docker Hub rate limiting (429 toomanyrequests); registry TLS issues; DNS hiccups — each retried. Non-existent tag (golang:<bad-version>) or denied repository becomes permanent and is returned unwrapped-classified.

Common situations: Unauthenticated Docker Hub pulls in CI hitting rate limits; corporate proxies intercepting registry traffic; pulling a GoVersion tag that was never published; flaky VPN/DNS.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/1d85113e0a388ef8. Report an issue: GitHub.