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

  1. Check the wrapped cause: if 401/403, the image/scope is not publicly pullable — supply credentials
  2. Verify connectivity from the node to the token realm URL (curl the realm endpoint)
  3. If behind a proxy, configure the client/proxy env so TLS to the realm works
  4. 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

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


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