AlistGo/alist · error

token is expired

Error message

token is expired

What it means

ParseToken maps jwt.ValidationErrorExpired to this message: the JWT parsed structurally but its exp claim (set from conf.Conf.TokenExpiresIn hours at issue time) is in the past.

Source

Thrown at server/common/auth.go:53

		return "", err
	}
	validTokenCache.Set(tokenString, true)
	return tokenString, err
}

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)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Catch this error and re-authenticate to get a new token (standard token refresh flow)
  2. Increase TokenExpiresIn in config.json for unattended clients, or set 0 if you want non-expiring tokens
  3. For automation, wrap API calls in a helper that transparently re-logins on 'token is expired'

Example fix

// before
resp, err := doRequest(token) // errors after 48h

// after
resp, err := doRequest(token)
if err != nil && strings.Contains(err.Error(), "expired") {
    token = login(username, password)
    resp, err = doRequest(token)
}
Defensive patterns

Strategy: retry

Try / catch

claims, err := common.ParseToken(tok)
if err != nil && strings.Contains(err.Error(), "expired") {
	tok = login(user, pass)
	claims, err = common.ParseToken(tok)
}

Prevention

When it happens

Trigger: Using a login token past its lifetime (default configured via TokenExpiresIn; 0 disables expiry in some configs).

Common situations: Long-lived scripts/CLI sessions holding a token for days; TokenExpiresIn lowered in config causing old tokens to lapse; server clock ahead of client.

Understand the failure class

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/fac7d044b123f020. Report an issue: GitHub.