{"record":{"id":"b7161da4c29fad58","repo":"AlistGo/alist","slug":"failed-to-decode-jwt-token","errorCode":null,"errorMessage":"failed to decode jwt token","messagePattern":"failed to decode jwt token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/aliyundrive_open/util.go","lineNumber":163,"sourceCode":"\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 {\n\t\t\twait := rateLimitErr.retryAfter\n\t\t\tif wait <= 0 {\n\t\t\t\twait = time.Duration(i+1) * 2 * time.Second\n\t\t\t}","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/aliyundrive_open/util.go#L145-L181","documentation":"Thrown by getSub() in the Aliyundrive Open driver when the JWT payload segment cannot be base64-decoded. The driver uses base64.RawStdEncoding.DecodeString on segments[1]; if the payload contains URL-safe characters ('-','_') or padding, standard decoding fails.","triggerScenarios":"refreshTokenWithPost calls getSub(d.RefreshToken) or getSub(refresh) where the token's middle segment is base64url-encoded (RFC 7515 style, common for JWS tokens) rather than raw standard base64, or the segment is otherwise malformed/truncated.","commonSituations":"Aliyun changed or issues tokens signed with a different encoding variant; the token was truncated when copied into storage config; a proxy mangled the token response body.","solutions":["Inspect the token's middle segment manually: echo '<payload>' | base64 -d vs base64 -d with urlsafe translation to confirm the encoding","Regenerate the refresh token via the official OAuth flow so a current, well-formed token is stored","Update the alist driver to a version where getSub handles base64.URL encoding if the provider changed format"],"exampleFix":"// before (util.go)\nbs, err := base64.RawStdEncoding.DecodeString(segments[1])\n// after: tolerate both encodings\nseg := strings.NewReplacer(\"-\", \"+\", \"_\", \"/\").Replace(segments[1])\nbs, err := base64.RawStdEncoding.DecodeString(seg)","handlingStrategy":"validation","validationCode":"func tryDecodeJWTPayload(seg string) ([]byte, error) {\n    if bs, err := base64.RawStdEncoding.DecodeString(seg); err == nil { return bs, nil }\n    if bs, err := base64.RawURLEncoding.DecodeString(seg); err == nil { return bs, nil }\n    return nil, errors.New(\"undecodable jwt payload\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to decode jwt token\") { seg := tokenSeg1; if _, e2 := base64.RawURLEncoding.DecodeString(seg); e2 == nil { /* encoding variant: handle urlsafe */ } }","preventionTips":["Treat base64 decode failure as a signal the token format changed","Normalize -/_ before RawStdEncoding decode","Keep the driver updated when providers rotate token formats"],"tags":["aliyundrive","jwt","base64","token-refresh","auth"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}