grpc/grpc-go · error
no expiration claims
Error message
no expiration claims
What it means
After unmarshalling, if claims.Exp == 0 (the zero value for int64) extractExpiration returns 'no expiration claims' (file_reader.go:106-108). The reader requires an exp claim because it needs to know when to consider the token dead; a JWT without exp is unusable for this credential.
Source
Thrown at credentials/jwt/file_reader.go:107
// extractExpiration parses the JWT token to extract the expiration time.
func (r *jwtFileReader) extractExpiration(token string) (time.Time, error) {
claimsRaw, ok := extractClaimsRaw(token)
if !ok {
return time.Time{}, fmt.Errorf("expected 3 parts in token")
}
payloadBytes, err := base64.RawURLEncoding.DecodeString(claimsRaw)
if err != nil {
return time.Time{}, fmt.Errorf("decode error: %v", err)
}
var claims jwtClaims
if err := json.Unmarshal(payloadBytes, &claims); err != nil {
return time.Time{}, fmt.Errorf("unmarshal error: %v", err)
}
if claims.Exp == 0 {
return time.Time{}, fmt.Errorf("no expiration claims")
}
expTime := time.Unix(claims.Exp, 0)
// Check if token is already expired.
if expTime.Before(time.Now()) {
return time.Time{}, fmt.Errorf("expired token")
}
return expTime, nil
}
View on GitHub (pinned to 03255a9237)
Solutions
- Configure the issuer to include a real exp (future Unix timestamp).
- If using a custom claims builder, ensure exp is set and non-zero.
- Switch to an ID-token source that always emits exp (GCP metadata server, OIDC provider).
Example fix
// before: token minted without exp
// {"iss":"svc","aud":"api"}
// after: issuer includes exp
// {"iss":"svc","aud":"api","exp":1735689600} Defensive patterns
Strategy: validation
Validate before calling
// Confirm exp is present and positive before use.
var c struct{ Exp int64 `json:"exp"` }
_ = json.Unmarshal(payloadBytes, &c)
if c.Exp == 0 {
return errors.New("token has no exp claim")
} Try / catch
_, _, err := r.readToken()
if err != nil && strings.Contains(err.Error(), "no expiration claims") {
// issuer dropped exp; reconfigure the issuer to include it.
return err
} Prevention
- Require the issuer to always emit a positive exp claim.
- Use ID-token sources that mandate exp (GCP metadata, OIDC providers).
- In custom claims builders, set exp explicitly.
- Reject tokens without exp at integration boundaries.
When it happens
Trigger: The JWT payload has no exp field, exp is absent, or the issuer emitted exp:0. Because jwtClaims only decodes exp, any other claim structure is fine — but exp must be a positive Unix timestamp.
Common situations: A token minted by an issuer configured without expiration, a misconfigured OIDC provider, or a service-account token minted with a custom claims override that dropped exp.
Related errors
- credentials: audience cannot be empty
- token file %q: %v: %w
- credentials: ctx cannot be nil
- unsupported mode: %v
- %v: %w
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/eb549c68923f7b47.
Report an issue: GitHub.