containerd/containerd · error
failed to fetch anonymous token: %w
Error message
failed to fetch anonymous token: %w
What it means
When no credentials are available, the docker authorizer requests an anonymous bearer token with auth.FetchToken (GET flow); any failure is wrapped as 'failed to fetch anonymous token'. It means the public token endpoint refused or failed the unauthenticated token request. The underlying error is preserved via %w.
Source
Thrown at core/remotes/docker/authorizer.go:345
return "", "", err
}
expirationTime = getExpirationTime(resp.ExpiresInSeconds)
return resp.Token, resp.RefreshToken, nil
}
log.G(ctx).WithFields(log.Fields{
"status": errStatus.Status,
"body": string(errStatus.Body),
}).Debugf("token request failed")
}
return "", "", err
}
expirationTime = getExpirationTime(resp.ExpiresInSeconds)
return resp.AccessToken, resp.RefreshToken, nil
}
// do request anonymously
resp, err := auth.FetchToken(ctx, ah.client, ah.header, to)
if err != nil {
return "", "", fmt.Errorf("failed to fetch anonymous token: %w", err)
}
expirationTime = getExpirationTime(resp.ExpiresInSeconds)
return resp.Token, resp.RefreshToken, nil
}
func getExpirationTime(expiresInSeconds int) *time.Time {
if expiresInSeconds <= 0 {
return nil
}
expirationTime := time.Now().Add(time.Duration(expiresInSeconds) * time.Second)
return &expirationTime
}
func invalidAuthorization(ctx context.Context, c auth.Challenge, responses []*http.Response) (retry bool, _ error) {
errStr := c.Parameters["error"]
if errStr == "" {
return retry, nil
}View on GitHub (pinned to 4246446a2b)
Solutions
- Check the wrapped cause: if 401/403, the image/scope is not publicly pullable — supply credentials
- Verify connectivity from the node to the token realm URL (curl the realm endpoint)
- If behind a proxy, configure the client/proxy env so TLS to the realm works
- Retry on transient 5xx; if persistent, check registry service health
Defensive patterns
Strategy: try-catch
Validate before calling
resp, err := http.Get(realm + "?service=" + service + "&scope=" + scope)
if err != nil || resp.StatusCode != http.StatusOK {
return fmt.Errorf("anonymous token for scope %s unavailable (status %v) — supply credentials", scope, status)
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "401") || strings.Contains(err.Error(), "403") {
// fall back to authenticated pull with credentials
}
return fmt.Errorf("anonymous token fetch failed: %w", err)
} Prevention
- Don't assume images are publicly pullable; configure creds for private repos
- Verify realm DNS/TLS from the runtime environment
- Handle transient 5xx with retry/backoff
- Check proxy env (HTTP_PROXY/HTTPS_PROXY) correctness on nodes
When it happens
Trigger: doBearerAuth with empty secret calls auth.FetchToken(ctx, ah.client, ah.header, to) and the GET to the realm token endpoint fails: non-2xx response, network error, TLS error, or invalid JSON token response.
Common situations: Pulling a private image anonymously (registry returns 401/denied for the scope); token service temporarily down; DNS or proxy misconfiguration in clusters; corporate MITM proxy breaking TLS to the realm; scope requiring auth though image metadata looked public.
Related errors
- authorization server did not include a token in the response
- failed to fetch oauth token: %w
- no realm specified for token auth challenge
- authorization failed
- stopped after 10 redirects
AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02).
Data as JSON: /api/errors/5c0120433c20fe69.
Report an issue: GitHub.