googleapis/mcp-toolbox · error
retrieved token is invalid or expired
Error message
retrieved token is invalid or expired
What it means
GetIAMAccessToken validates the token returned by the TokenSource using token.Valid(), which checks that the access token is non-empty, has an expiry, and is not expired. This error means the oauth2 library handed back a token that failed those invariants — practically a bug/edge case in credential setup, such as a credentials type that yields empty access tokens.
Source
Thrown at internal/sources/util.go:158
return "", fmt.Errorf("username from ADC cannot be an empty string")
}
return username, nil
}
func GetIAMAccessToken(ctx context.Context) (string, error) {
creds, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/cloud-platform")
if err != nil {
return "", fmt.Errorf("failed to find default credentials (run 'gcloud auth application-default login'?): %w", err)
}
token, err := creds.TokenSource.Token() // This gets an oauth2.Token
if err != nil {
return "", fmt.Errorf("failed to get token from token source: %w", err)
}
if !token.Valid() {
return "", fmt.Errorf("retrieved token is invalid or expired")
}
return token.AccessToken, nil
}
View on GitHub (pinned to 8cc6e09de2)
Solutions
- Re-generate credentials: 'gcloud auth application-default login' or a fresh service account key
- Fix system clock synchronization (chrony/ntp)
- Verify the ADC key file is a genuine, complete Google-issued credential file
Defensive patterns
Strategy: retry
Validate before calling
// Validate token before use
function tokenLooksValid(t: { access_token?: string; expiry_date?: number }): boolean {
return !!t.access_token && typeof t.expiry_date === "number" && t.expiry_date > Date.now();
} Type guard
function isUsableToken(t: { access_token: string; expiry_date?: number } | undefined | null):
t is { access_token: string; expiry_date?: number } {
return !!t && typeof t.access_token === "string" && t.access_token.length > 0;
} Try / catch
try {
const token = await getIAMAccessToken(ctx);
} catch (err) {
if (String(err).includes("retrieved token is invalid or expired")) {
// force-refresh credentials once, then retry
await refreshCredentials();
return getIAMAccessToken(ctx);
}
throw err;
} Prevention
- Keep NTP/chrony time sync enabled; clock skew is the usual cause
- Re-download ADC keys from Google rather than hand-editing them
- If it recurs, request tokens through an official client library that auto-refreshes
When it happens
Trigger: creds.TokenSource.Token() returns successfully but the token has an empty AccessToken, zero Expiry, or is already expired at return time — e.g. unusual/invalid credential configurations or mocked/edge-case ADC sources.
Common situations: ADC pointing to a key file whose token endpoint returns an empty access token; heavily skewed system clocks making the token immediately expired; using non-standard credential files hand-crafted or copied between environments.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- error creating service from OAuth access token: %w
- failed to get token from token source: %w
- failed to create DataChatClient: %w
- failed to find default credentials: %w
- error creating service from ADC: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/9edcfe5d620e804a.
Report an issue: GitHub.