docker/cli · error
failed to parse token claims
Error message
failed to parse token claims: %w
What it means
Returned by OAuthManager.Login when oauth.GetClaims(tokenRes.AccessToken) fails. After the device flow returns an access token, the manager parses its JWT claims to extract the username/domain; if the token is malformed or claims cannot be extracted, login aborts before storing anything.
Solutions
- Retry `docker login` to obtain a fresh access token.
- Update the CLI to the latest version (GetClaims contract may have changed).
- Check no proxy is mutating the token body.
- If recurring, fall back to a manual PAT login.
Example fix
# before docker login # -> failed to parse token claims docker logout docker login # fresh token # fallback docker login -u myuser # PAT as password
Defensive patterns
Strategy: try-catch
Try / catch
// claims parse failure -> retry once, then fall back to PAT login
if strings.Contains(err.Error(), "failed to parse token claims") { fallBackToPAT() } Prevention
- Keep the CLI current with the tenant's token format.
- Ensure no proxy truncates the JWT.
- Maintain a PAT fallback path.
When it happens
Trigger: The tenant issued an access token that is not a parseable JWT or whose claims do not contain the expected domain/username fields.
Common situations: Tenant returned a non-JWT bearer token; token was truncated/mangled by a proxy; tenant schema change; clock/signature verification failure inside GetClaims.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to get tokens
- failed to decode response
- unexpected response from Hub
- failed waiting for authentication
- failed to store tokens
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/4ba0802ad912f1f7.
Report an issue: GitHub.
Appendix: source
Thrown at internal/oauth/manager/manager.go:139
go func() {
reader := bufio.NewReader(os.Stdin)
_, _ = reader.ReadString('\n')
_ = m.openBrowser(state.VerificationURI)
}()
_, _ = fmt.Fprint(w, "\nWaiting for authentication in the browser…\n")
var tokenRes api.TokenResponse
select {
case <-ctx.Done():
return nil, errors.New("login canceled")
case err := <-waitForTokenErrChan:
return nil, fmt.Errorf("failed waiting for authentication: %w", err)
case tokenRes = <-tokenResChan:
}
claims, err := oauth.GetClaims(tokenRes.AccessToken)
if err != nil {
return nil, fmt.Errorf("failed to parse token claims: %w", err)
}
err = m.storeTokensInStore(tokenRes, claims.Domain.Username)
if err != nil {
return nil, fmt.Errorf("failed to store tokens: %w", err)
}
pat, err := m.api.GetAutoPAT(ctx, m.audience, tokenRes)
if err != nil {
return nil, err
}
return &types.AuthConfig{
Username: claims.Domain.Username,
Password: pat,
ServerAddress: registry.IndexServer,
}, nil
}View on GitHub (pinned to 4f84911bfe)