{"record":{"id":"d5e9d0ce8c3c0df6","repo":"AlistGo/alist","slug":"not-a-jwt-token-because-of-invalid-segments","errorCode":null,"errorMessage":"not a jwt token because of invalid segments","messagePattern":"not a jwt token because of invalid segments","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/aliyundrive_open/util.go","lineNumber":159,"sourceCode":"\t}\n\tcurSub, err := getSub(d.RefreshToken)\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\tnewSub, err := getSub(refresh)\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\tif curSub != newSub {\n\t\treturn \"\", \"\", errors.New(\"failed to refresh token: sub not match\")\n\t}\n\treturn refresh, access, nil\n}\n\nfunc getSub(token string) (string, error) {\n\tsegments := strings.Split(token, \".\")\n\tif len(segments) != 3 {\n\t\treturn \"\", errors.New(\"not a jwt token because of invalid segments\")\n\t}\n\tbs, err := base64.RawStdEncoding.DecodeString(segments[1])\n\tif err != nil {\n\t\treturn \"\", errors.New(\"failed to decode jwt token\")\n\t}\n\treturn utils.Json.Get(bs, \"sub\").ToString(), nil\n}\n\nfunc (d *AliyundriveOpen) refreshToken(ctx context.Context) error {\n\tif d.ref != nil {\n\t\treturn d.ref.refreshToken(ctx)\n\t}\n\trefresh, access, err := d._refreshToken(ctx)\n\tfor i := 0; i < 3; i++ {\n\t\tif err == nil {\n\t\t\tbreak\n\t\t}\n\t\tif rateLimitErr, ok := err.(*refreshRateLimitError); ok {","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/aliyundrive_open/util.go#L141-L177","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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"],"exampleFix":"// before: stale refresh token in config\nrefresh_token: \" eyJhbGci...truncated\"\n// after: regenerate via oauth flow and paste complete token\nrefresh_token: \"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ4eCJ9.sig\"","handlingStrategy":"validation","validationCode":"func isJWT(token string) bool {\n    return len(strings.Split(strings.TrimSpace(token), \".\")) == 3\n}\n// before calling refreshToken:\nif !isJWT(d.RefreshToken) { return fmt.Errorf(\"stored refresh token is not a JWT; re-authenticate\") }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"invalid segments\") { /* re-obtain refresh token, do not retry with same value */ }","preventionTips":["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"],"tags":["aliyundrive","jwt","oauth","token-refresh","auth"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}