{"record":{"id":"91844301be2f6795","repo":"AlistGo/alist","slug":"failed-to-refresh-token-w","errorCode":null,"errorMessage":"failed to refresh token: %w","messagePattern":"failed to refresh token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/doubao/util.go","lineNumber":388,"sourceCode":"\n\t\t_, err := d.requestApi(uploadUrl, http.MethodGet, tokenType, func(req *resty.Request) {\n\t\t\treq.SetQueryParams(params)\n\t\t}, &configResp)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif configResp.ResponseMetadata.Error.Code == \"\" {\n\t\t\t*upConfig = configResp.Result\n\t\t\treturn nil\n\t\t}\n\n\t\t// 100028 凭证过期\n\t\tif configResp.ResponseMetadata.Error.CodeN == 100028 && !tokenRefreshed {\n\t\t\tlog.Debugln(\"[doubao] Upload token expired, re-fetching...\")\n\t\t\tnewToken, err := d.initUploadToken()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to refresh token: %w\", err)\n\t\t\t}\n\n\t\t\td.UploadToken = newToken\n\t\t\ttokenRefreshed = true\n\t\t\tuploadUrl, params = configureParams()\n\n\t\t\treturn retry.Error{errors.New(\"token refreshed, retry needed\")}\n\t\t}\n\n\t\treturn fmt.Errorf(\"get upload_config failed: %s\", configResp.ResponseMetadata.Error.Message)\n\t})\n\n\treturn err\n}\n\n// uploadNode 上传 文件信息\nfunc (d *Doubao) uploadNode(uploadConfig *UploadConfig, dir model.Obj, file model.FileStreamer, dataType string) (UploadNodeResp, error) {\n\treqUuid := uuid.New().String()","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/doubao/util.go#L370-L406","documentation":"During getUploadConfig, the Doubao backend returned error code 100028 (upload token/credentials expired). The driver attempted to re-fetch the upload token via initUploadToken, and that re-fetch itself failed; the %w wraps the initUploadToken error. The upload cannot proceed without valid STS credentials.","triggerScenarios":"initUploadToken fails because the underlying session cookie is expired/invalid (the same stale credentials that caused 100028), the account is rate-limited, or the token endpoint is temporarily unavailable. The tokenRefreshed guard means only one refresh attempt happens per retry cycle.","commonSituations":"Long-running mounts where the login cookie expired while the upload token also lapsed — refresh needs a valid session but the session is the broken piece; concurrent uploads racing the single token refresh.","solutions":["Re-login: update the cookie/credentials in the Doubao driver config, then retry the upload (most common fix — the refresh uses the same dead session)","If the wrapped error mentions rate limiting, back off and retry after a minute","Restart the mount/process to clear stale in-memory UploadToken state after credential rotation"],"exampleFix":"// before\nnewToken, err := d.initUploadToken()\nif err != nil {\n\treturn fmt.Errorf(\"failed to refresh token: %w\", err)\n}\n// after — make the auth root cause explicit\nnewToken, err := d.initUploadToken()\nif err != nil {\n\treturn fmt.Errorf(\"failed to refresh expired upload token (session cookie likely expired, re-login): %w\", err)\n}","handlingStrategy":"retry","validationCode":"if d.Cookie == \"\" || cookieAge(d.Cookie) > sessionTTL {\n\treturn errors.New(\"doubao session cookie stale — re-login before upload\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to refresh token\") {\n\t// root cause is almost always the session cookie: reconfigure and retry whole upload\n\treturn reloginThenRetryUpload()\n}","preventionTips":["Rotate the cookie on a schedule before token expiry windows","Restart the mount after credential changes to clear in-memory tokens","Avoid concurrent first-uploads racing the single refresh"],"tags":["doubao","auth","token-expiry","upload"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}