amir20/dozzle · error

registry returned for

Error message

registry returned %s for %s

What it means

Digest queries the registry's manifests endpoint and switches on the response status. Known cases (401, 404, 429) map to sentinel errors; any other non-success status (5xx, 403 with unusual body, unexpected codes) produces this generic error containing the raw status line and repository.

Solutions

  1. Read resp.Status in the error to see the exact code and retry later for 5xx
  2. Check the registry/mirror health and logs
  3. If behind a proxy, verify it forwards registry auth headers and does not rewrite responses
  4. Add retry with backoff for transient 5xx statuses
  5. Consider handling the new status code explicitly in registry.go if it recurs
Defensive patterns

Strategy: retry

Try / catch

d, err := client.Digest(ref)
if err != nil {
    switch {
    case errors.Is(err, imagecheck.ErrAuthRequired),
         errors.Is(err, imagecheck.ErrNotFound),
         errors.Is(err, imagecheck.ErrRateLimited):
        return handleSentinel(err)
    default: // includes "registry returned ..."
        return retryWithBackoff(func() error { _, err = client.Digest(ref); return err })
    }
}

Prevention

When it happens

Trigger: The registry HTTP response status is not one of the handled codes, e.g. 500 from Docker Hub, 503 from a mirror under load, or 403 from a proxy that rejects the request in an unexpected way.

Common situations: Docker Hub transient outages (5xx), corporate proxies intercepting registry traffic, self-hosted registries (Harbor, GitLab) misconfigured and returning unusual status codes, or a mirror returning 451/502.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/d36a7fe168131931. Report an issue: GitHub.

Appendix: source

Thrown at internal/imagecheck/registry.go:111

	}
	defer resp.Body.Close()

	log.Debug().
		Str("repository", ref.Repository).
		Int("status", resp.StatusCode).
		Str("contentType", resp.Header.Get("Content-Type")).
		Msg("image update check: manifest response")

	switch resp.StatusCode {
	case http.StatusOK:
	case http.StatusUnauthorized, http.StatusForbidden:
		return "", ErrAuthRequired
	case http.StatusNotFound:
		return "", ErrNotFound
	case http.StatusTooManyRequests:
		return "", ErrRateLimited
	default:
		return "", fmt.Errorf("registry returned %s for %s", resp.Status, ref.Repository)
	}

	digest := resp.Header.Get("Docker-Content-Digest")
	if digest == "" {
		return "", fmt.Errorf("registry omitted Docker-Content-Digest for %s", ref.Repository)
	}

	log.Debug().Str("repository", ref.Repository).Str("digest", digest).Msg("image update check: registry digest")

	return digest, nil
}

func (r *Registry) head(ctx context.Context, ref Reference, token string) (*http.Response, error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodHead, ref.manifestURL(), nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Accept", acceptManifests)

View on GitHub (pinned to d9463cbe21)