{"record":{"id":"9060eb7597941c6e","repo":"AlistGo/alist","slug":"get-upload-token-failed-s","errorCode":null,"errorMessage":"get upload token failed: %s","messagePattern":"get upload token failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/guangyapan/driver.go","lineNumber":897,"sourceCode":"\treturn fmt.Errorf(\"task %s timeout\", taskID)\n}\n\nfunc (d *GuangYaPan) getUploadToken(ctx context.Context, parentID, name string, size int64) (*uploadTokenData, int, error) {\n\tvar out uploadTokenResp\n\terr := d.postAPI(ctx, \"/nd.bizuserres.s/v1/get_res_center_token\", map[string]any{\n\t\t\"capacity\": 2,\n\t\t\"name\":     name,\n\t\t\"parentId\": parentID,\n\t\t\"res\": map[string]any{\n\t\t\t\"fileSize\": size,\n\t\t},\n\t}, &out)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\tmsg := strings.TrimSpace(out.Msg)\n\tif msg != \"\" && !strings.EqualFold(msg, \"success\") {\n\t\treturn nil, out.Code, fmt.Errorf(\"get upload token failed: %s\", msg)\n\t}\n\tif out.Data.TaskID == \"\" {\n\t\treturn nil, out.Code, errors.New(\"get upload token failed: empty task id\")\n\t}\n\tif out.Data.AccessKeyID == \"\" {\n\t\tout.Data.AccessKeyID = out.Data.Creds.AccessKeyID\n\t}\n\tif out.Data.SecretAccessKey == \"\" {\n\t\tout.Data.SecretAccessKey = out.Data.Creds.SecretAccessKey\n\t}\n\tif out.Data.SessionToken == \"\" {\n\t\tout.Data.SessionToken = out.Data.Creds.SessionToken\n\t}\n\tif strings.TrimSpace(out.Data.EndPoint) == \"\" {\n\t\tout.Data.EndPoint = strings.TrimSpace(out.Data.FullEndPoint)\n\t}\n\tif strings.TrimSpace(out.Data.EndPoint) != \"\" && !strings.HasPrefix(out.Data.EndPoint, \"http://\") && !strings.HasPrefix(out.Data.EndPoint, \"https://\") {\n\t\tif strings.TrimSpace(out.Data.FullEndPoint) != \"\" {","sourceCodeStart":879,"sourceCodeEnd":915,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/guangyapan/driver.go#L879-L915","documentation":"getUploadToken calls /nd.bizuserres.s/v1/get_res_center_token with the file name, parent, and size; it throws when the envelope Msg is present but not 'success'. (Empty-task-id and credential-fallback cases are separate errors.) The provider is rejecting the upload authorization itself.","triggerScenarios":"Requesting an upload token for a file that exceeds account quota or per-file limits, an invalid parentId/name, a non-premium account hitting capacity=2 restrictions, or provider-side errors.","commonSituations":"Uploading a file larger than the plan allows; parent folder deleted mid-upload; free-tier limits on res-center uploads; API contract change adding a required field.","solutions":["Read the embedded Msg - quota/limit messages point at plan limits; trim the upload or upgrade.","Verify the destination folder still exists before retrying.","Retry once for transient server messages."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// pre-checks before requesting an upload token\nif size > maxPlanSize { // set from your plan's per-file limit\n    return fmt.Errorf(\"file %d bytes exceeds plan limit\", size)\n}\nif strings.TrimSpace(name) == \"\" || strings.ContainsAny(name, \"\\\\/:*?\\\"<>|\") {\n    return errors.New(\"file name empty or contains illegal characters\")\n}","typeGuard":null,"tryCatchPattern":"if _, _, err := d.getUploadToken(ctx, parentID, name, size); err != nil {\n    if strings.Contains(err.Error(), \"get upload token failed\") {\n        // authorization rejected: surface quota/limit msg to user, do not retry blindly\n        return fmt.Errorf(\"upload rejected by provider: %w\", err)\n    }\n    return err\n}","preventionTips":["Check account quota and per-file size limits before large uploads.","Confirm the destination folder exists at upload time, not at task-planning time."],"tags":["upload","quota","token","guangyapan"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}