amir20/dozzle · error

invalid auth realm

Error message

invalid auth realm %q: %w

What it means

In Registry.token the WWW-Authenticate challenge's realm string could not be parsed as a URL (url.Parse failed), so the registry returned a malformed token endpoint. The registry URL comes from the registry's own response header, meaning the upstream registry is misbehaving; the error wraps the underlying parse error via %w.

Solutions

  1. Inspect the registry's WWW-Authenticate header; the realm must be an absolute URL.
  2. Retry the check later if the registry is misconfigured server-side.
  3. Treat image update checks as best-effort: log and skip the update check instead of failing the request.
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at internal/imagecheck/registry.go:158 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at internal/imagecheck/registry.go:158

func (r *Registry) token(ctx context.Context, ref Reference, challenge string) (string, error) {
	key := ref.host() + "/" + ref.Repository

	r.mu.Lock()
	if cached, ok := r.tokens[key]; ok && time.Now().Before(cached.expiresAt) {
		r.mu.Unlock()
		log.Debug().Str("repository", ref.Repository).Msg("image update check: reusing cached token")
		return cached.token, nil
	}
	r.mu.Unlock()

	realm, service := parseChallenge(challenge)
	if realm == "" {
		return "", ErrAuthRequired
	}

	endpoint, err := url.Parse(realm)
	if err != nil {
		return "", fmt.Errorf("invalid auth realm %q: %w", realm, err)
	}

	// The realm is chosen by the registry, so it decides where Dozzle sends
	// its next request. Requiring TLS stops a hostile or compromised registry
	// from pointing that request at a plaintext internal address such as a
	// cloud metadata endpoint. Loopback registries are exempt for the same
	// reason they are allowed over HTTP at all.
	if err := validateRealm(endpoint, ref); err != nil {
		return "", err
	}
	query := endpoint.Query()
	if service != "" {
		query.Set("service", service)
	}
	query.Set("scope", "repository:"+ref.Repository+":pull")
	endpoint.RawQuery = query.Encode()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)

View on GitHub (pinned to d9463cbe21)