AlistGo/alist · error
not a jwt token because of invalid segments
Error message
not a jwt token because of invalid segments
What it means
Thrown by getSub() in the Aliyundrive Open driver while refreshing the OAuth token. After a successful refresh, the driver splits the refresh token on '.' and expects exactly 3 JWT segments (header.payload.signature); any other shape means the string is not a JWT and the sub-claim comparison cannot be done.
Source
Thrown at drivers/aliyundrive_open/util.go:159
}
curSub, err := getSub(d.RefreshToken)
if err != nil {
return "", "", err
}
newSub, err := getSub(refresh)
if err != nil {
return "", "", err
}
if curSub != newSub {
return "", "", errors.New("failed to refresh token: sub not match")
}
return refresh, access, nil
}
func getSub(token string) (string, error) {
segments := strings.Split(token, ".")
if len(segments) != 3 {
return "", errors.New("not a jwt token because of invalid segments")
}
bs, err := base64.RawStdEncoding.DecodeString(segments[1])
if err != nil {
return "", errors.New("failed to decode jwt token")
}
return utils.Json.Get(bs, "sub").ToString(), nil
}
func (d *AliyundriveOpen) refreshToken(ctx context.Context) error {
if d.ref != nil {
return d.ref.refreshToken(ctx)
}
refresh, access, err := d._refreshToken(ctx)
for i := 0; i < 3; i++ {
if err == nil {
break
}
if rateLimitErr, ok := err.(*refreshRateLimitError); ok {View on GitHub (pinned to 843d9dc814)
Solutions
- Check the debug log line '[ali_open] refresh token response: ...' to see what the server actually returned; if it is an error page, fix connectivity or credentials
- Re-obtain a valid refresh_token from the Aliyun Open platform QR/OAuth flow and update the storage configuration
- Verify ClientID/ClientSecret match the app that issued the token; mismatched credentials produce nonstandard responses
- If the response is valid JSON but the token field is opaque, ensure you are on a recent driver version compatible with the current API
Example fix
// before: stale refresh token in config refresh_token: " eyJhbGci...truncated" // after: regenerate via oauth flow and paste complete token refresh_token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ4eCJ9.sig"
Defensive patterns
Strategy: validation
Validate before calling
func isJWT(token string) bool {
return len(strings.Split(strings.TrimSpace(token), ".")) == 3
}
// before calling refreshToken:
if !isJWT(d.RefreshToken) { return fmt.Errorf("stored refresh token is not a JWT; re-authenticate") } Try / catch
if err != nil && strings.Contains(err.Error(), "invalid segments") { /* re-obtain refresh token, do not retry with same value */ } Prevention
- Store only complete tokens obtained from the official OAuth flow
- Validate 3-segment shape before persisting a refresh token
- Log the raw refresh response at debug level for post-mortems
When it happens
Trigger: A call to refreshTokenWithPost (POST to the aliyundrive open OAuth endpoint with grant_type=refresh_token) returns a refresh_token that is not a 3-segment JWT — e.g. an opaque token, an HTML/XML error page captured as a token, or an empty string with surrounding whitespace. getSub is called on both d.RefreshToken and the newly returned token.
Common situations: The API returned an error body that was not detected as an ErrResp (non-JSON error page, CDN/WAF interstitial), the account's refresh token was rotated or revoked so the response contains a different token format, or the stored refresh token in the storage config is stale/corrupted (bad copy-paste).
Related errors
- failed to decode jwt token
- failed to refresh token: refresh token is empty
- failed to refresh token: sub not match
- e.Message
- refresh token is empty
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/d5e9d0ce8c3c0df6.
Report an issue: GitHub.