vxcontrol/pentagi · error
token is invalid
Error message
token is invalid
What it means
After parsing succeeds with no error, ValidateAPIToken double-checks token.Valid; if false it returns "token is invalid". With jwt/v5 this is a defensive branch — if ParseWithClaims returned no error, token.Valid is normally true — but it guards against any parser state where claims parsed yet validity was not established.
Source
Thrown at backend/pkg/server/auth/api_token_jwt.go:58
token, err := jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (any, error) {
// verify signing algorithm to prevent "alg: none"
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return MakeJWTSigningKey(globalSalt), nil
})
if err != nil {
if errors.Is(err, jwt.ErrTokenMalformed) {
return nil, fmt.Errorf("token is malformed")
} else if errors.Is(err, jwt.ErrTokenExpired) || errors.Is(err, jwt.ErrTokenNotValidYet) {
return nil, fmt.Errorf("token is either expired or not active yet")
} else {
return nil, fmt.Errorf("token invalid: %w", err)
}
}
if !token.Valid {
return nil, fmt.Errorf("token is invalid")
}
return &claims, nil
}
View on GitHub (pinned to ea665308ba)
Solutions
- Treat as a hard authentication failure: reject the request and return 401
- Log token subject/tokenID (never the raw token) to identify which credential failed
- Pin/verify the golang-jwt/jwt/v5 version for consistent Valid semantics
- Report upstream if reproducible, including how the token was constructed
Defensive patterns
Strategy: type-guard
Type guard
func isHardInvalid(err error) bool {
return err != nil && strings.Contains(err.Error(), "token is invalid")
} Try / catch
claims, err := auth.ValidateAPIToken(tok, salt)
if err != nil {
if strings.Contains(err.Error(), "token is invalid") {
log.Error("parser returned non-valid token without error; failing closed")
}
return err // always fail closed
} Prevention
- Fail closed: treat this branch as an unconditional auth rejection
- Pin the golang-jwt/jwt/v5 version and review its release notes on upgrades
- Avoid custom validation hooks that mutate token validity without returning errors
- Report reproducible cases upstream with reproduction steps
When it happens
Trigger: Practically only reached if a future/patched jwt/v5 behavior returns err==nil with token.Valid==false, or custom claims' validation hooks invalidate the token without returning an error that maps to the other branches.
Common situations: Upgrading golang-jwt/jwt versions introduces new validity semantics; test mocks returning a non-valid token with nil error.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- token is invalid
- token is malformed
- token is either expired or not active yet
- token invalid: %w
- cookie claim invalid
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/d29d3523dd478467.
Report an issue: GitHub.