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

  1. 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
  2. Re-obtain a valid refresh_token from the Aliyun Open platform QR/OAuth flow and update the storage configuration
  3. Verify ClientID/ClientSecret match the app that issued the token; mismatched credentials produce nonstandard responses
  4. 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

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


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