{"record":{"id":"46c7d26342cc0f3e","repo":"AlistGo/alist","slug":"resp-errmsg","errorCode":null,"errorMessage":"resp.Errmsg","messagePattern":"resp\\.Errmsg","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/yunpan360/util.go","lineNumber":213,"sourceCode":"\t\t\t\"grant_type\":    \"authorization_code\",\n\t\t\t\"sub_channel\":   d.SubChannel,\n\t\t\t\"api_key\":       d.APIKey,\n\t\t})\n\n\tres, err := req.Get(reqURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar resp OpenAuthResp\n\tif err := utils.Json.Unmarshal(res.Body(), &resp); err != nil {\n\t\treturn nil, err\n\t}\n\tif resp.Errno != 0 {\n\t\tif resp.Errmsg == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"yunpan auth failed: errno=%d\", resp.Errno)\n\t\t}\n\t\treturn nil, errors.New(resp.Errmsg)\n\t}\n\n\tauth := &OpenAuthInfo{\n\t\tAccessToken: resp.Data.AccessToken,\n\t\tQid:         resp.Data.Qid,\n\t\tToken:       resp.Data.Token,\n\t\tSubChannel:  d.SubChannel,\n\t}\n\td.cachedOpenAuth = auth\n\td.openAuthExpire = time.Now().Add(50 * time.Minute)\n\n\tcopied := *auth\n\treturn &copied, nil\n}\n\nfunc (d *Yunpan360) openBaseParams(auth *OpenAuthInfo, method string, signParams map[string]string, withSign bool) map[string]string {\n\tparams := map[string]string{\n\t\t\"method\":       method,","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/yunpan360/util.go#L195-L231","documentation":"Thrown by the yunpan360 Open API authentication flow when the auth endpoint responds with a non-zero Errno. The server's Errmsg is returned as-is; this error means the driver could not obtain an AccessToken/Qid/Token triple, so all subsequent Open-API calls will fail.","triggerScenarios":"Calling the Open auth endpoint (OpenAuthResp decode in drivers/yunpan360/util.go:213) with an invalid/expired app token, wrong SubChannel, malformed credentials, or when the 360 Open platform rejects the sign-in. Any operation that triggers d.openAuth() (listing, upload, download via Open API) can surface it.","commonSituations":"Expired Open API token past the 50-minute cache window with refresh rejected; credentials copied incorrectly (trailing whitespace, wrong app key); the 360 Open platform account hit a quota or was disabled; clock skew breaking signed requests.","solutions":["Re-enter or refresh the Open API token/credentials in the storage config","Confirm the token belongs to the correct 360 Open app and account (SubChannel matches)","Check the errno value accompanying the auth failure — relogin-type errnos mean the stored token is dead and must be re-issued","If auth keeps failing right after success, verify server clock and credential formatting"],"exampleFix":"// before\nreturn nil, errors.New(resp.Errmsg)\n\n// after: keep errno context\nreturn nil, fmt.Errorf(\"yunpan auth failed: errno=%d: %s\", resp.Errno, resp.Errmsg)","handlingStrategy":"retry","validationCode":"if strings.TrimSpace(d.Addition.Token) == \"\" { return errs.EmptyToken }","typeGuard":"func isAuthErr(err error) bool { return err != nil && (strings.Contains(err.Error(), \"yunpan auth failed\") || strings.Contains(err.Error(), \"errno=\")) }","tryCatchPattern":"auth, err := d.openAuth(ctx)\nif err != nil {\n    // clear 50-min cache so next call re-authenticates\n    d.openAuthExpire = time.Time{}\n    auth, err = d.openAuth(ctx)\n    if err != nil { return nil, err }\n}","preventionTips":["Store the Open token exactly as issued; no extra whitespace","Treat repeated auth failures as a dead token — re-issue rather than retry-looping","Monitor auth refreshes; a refresh storm usually means a revoked token"],"tags":["yunpan360","auth","open-api","go"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}