fish2018/pansou · error
invalid token
Error message
invalid token
What it means
After parsing, ValidateToken checks token.Valid; if the parser returned no error but the token is not valid (expired, malformed claims, failed validation), it returns this sentinel "invalid token" error.
Solutions
- Have the client obtain a fresh token via LoginHandler and retry
- Check for expiry specifically (errors.Is(err, jwt.ErrTokenExpired) / validate errors) and return 401 prompting re-login
- Implement token refresh so clients renew before expiry
- Synchronize server clocks if skew is the cause
Example fix
// before
claims, err := util.ValidateToken(tokenString, secret)
if err != nil { c.AbortWithStatusJSON(401, gin.H{"error": "unauthorized"}); return }
// after
claims, err := util.ValidateToken(tokenString, secret)
if err != nil {
c.AbortWithStatusJSON(401, gin.H{"error": "invalid or expired token, please login again"})
return
} Defensive patterns
Strategy: try-catch
Validate before calling
// check expiry locally before calling API
claims, _, _ := parseUnverified(tokenString)
if claims != nil && time.Now().After(claims.ExpiresAt.Time) { refreshToken() } Try / catch
claims, err := util.ValidateToken(tokenString, secret)
if err != nil {
// treat as expired: redirect to login or refresh token
c.AbortWithStatusJSON(401, gin.H{"error": "token expired"})
return
} Prevention
- Implement token refresh before expiry
- Set reasonable expiry durations at issuance
- Handle 401 by re-authenticating automatically
When it happens
Trigger: Validating an expired JWT (exp in the past), a token whose claims fail validation, or a tampered token that happens to parse but fails validity checks.
Common situations: Long-lived client sessions past expiry; clock skew between issuer and validator; user keeps using a token after secret rotation.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- username cannot be empty
- token cannot be empty
- login required
- loginResp.Message (dynamic remote login failure message)
- secret cannot be empty
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/57e0d38da8a459bf.
Report an issue: GitHub.
Appendix: source
Thrown at util/jwt.go:63
return nil, errors.New("secret cannot be empty")
}
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
// 验证签名算法
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, errors.New("unexpected signing method")
}
return []byte(secret), nil
})
if err != nil {
return nil, err
}
if !token.Valid {
return nil, errors.New("invalid token")
}
return claims, nil
}
View on GitHub (pinned to beaa561337)