AlistGo/alist · error
couldn't handle this token
Error message
couldn't handle this token
What it means
ParseToken's fallback inside the ValidationError branch: the JWT library reported a validation error that is neither Malformed, Expired, nor NotValidYet — typically a signature validation failure (ValidationErrorSignatureInvalid) from signing with a different key.
Source
Thrown at server/common/auth.go:57
}
func ParseToken(tokenString string) (*UserClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
return SecretKey, nil
})
if IsTokenInvalidated(tokenString) {
return nil, errors.New("token is invalidated")
}
if err != nil {
if ve, ok := err.(*jwt.ValidationError); ok {
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
return nil, errors.New("that's not even a token")
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
return nil, errors.New("token is expired")
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
return nil, errors.New("token not active yet")
} else {
return nil, errors.New("couldn't handle this token")
}
}
}
if claims, ok := token.Claims.(*UserClaims); ok && token.Valid {
return claims, nil
}
return nil, errors.New("couldn't handle this token")
}
func InvalidateToken(tokenString string) error {
if tokenString == "" {
return nil // don't invalidate empty guest token
}
validTokenCache.Del(tokenString)
return nil
}
func IsTokenInvalidated(tokenString string) bool {View on GitHub (pinned to 843d9dc814)
Solutions
- Re-login to obtain a token signed by the current instance's key
- Pin the JWT secret in config so restarts do not rotate it
- Share the same secret across all instances that must verify each other's tokens
Example fix
# before (config.json) "jwt_secret": "" # regenerated each deploy -> old tokens fail # after "jwt_secret": "a-long-stable-random-value"
Defensive patterns
Strategy: try-catch
Try / catch
_, err := common.ParseToken(tok)
if err != nil && strings.Contains(err.Error(), "couldn't handle this token") {
c.AbortWithStatusJSON(401, gin.H{"error": "token rejected"})
return
} Prevention
- Pin the jwt_secret in config so restarts do not rotate it
- Share one secret across instances that verify each other's tokens
When it happens
Trigger: Verifying a token signed with a different SecretKey: alist restarted with a regenerated secret, a token from another instance/deployment, or a hand-forged signature.
Common situations: alist generates a random JWT secret on first run; wiping data or changing the secret invalidates all outstanding tokens. Multi-instance setups where instances do not share the secret.
Related errors
- token is invalidated
- that's not even a token
- token is expired
- token not active yet
- failed to refresh token: sub not match
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/6c13e758e91a6e3c.
Report an issue: GitHub.