{"record":{"id":"909f0234b43e7ad8","repo":"AlistGo/alist","slug":"res-status","errorCode":null,"errorMessage":"res.Status","messagePattern":"res\\.Status","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/cloudreve/util.go","lineNumber":275,"sourceCode":"\t\t}\n\t\treq, err := http.NewRequest(\"POST\", uploadUrl+\"?chunk=\"+strconv.Itoa(chunk),\n\t\t\tdriver.NewLimitedUploadStream(ctx, bytes.NewReader(byteData)))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treq = req.WithContext(ctx)\n\t\treq.ContentLength = byteSize\n\t\t// req.Header.Set(\"Content-Length\", strconv.Itoa(int(byteSize)))\n\t\treq.Header.Set(\"Authorization\", fmt.Sprint(credential))\n\t\treq.Header.Set(\"User-Agent\", d.getUA())\n\t\terr = func() error {\n\t\t\tres, err := base.HttpClient.Do(req)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer res.Body.Close()\n\t\t\tif res.StatusCode != 200 {\n\t\t\t\treturn errors.New(res.Status)\n\t\t\t}\n\t\t\tbody, err := io.ReadAll(res.Body)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tvar up Resp\n\t\t\terr = json.Unmarshal(body, &up)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif up.Code != 0 {\n\t\t\t\treturn errors.New(up.Msg)\n\t\t\t}\n\t\t\treturn nil\n\t\t}()\n\t\tif err == nil {\n\t\t\tretryCount = 0\n\t\t\tfinish += byteSize","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/cloudreve/util.go#L257-L293","documentation":"Surfaces during Cloudreve local-policy chunked upload: after PUTting a chunk with base.HttpClient.Do, the HTTP status is not 200 and res.Status (e.g. '403 Forbidden') is returned as the error. It reflects a transport/HTTP-level rejection of the chunk upload itself, before any JSON envelope is parsed.","triggerScenarios":"upLocal retry loop: request built with the upload credential URL, executed, res.StatusCode != 200. Produced by expired/one-time upload credentials, wrong Content-Length, blocked origin, or Cloudrebve returning 404/403 for the session upload URL.","commonSituations":"Upload session credential expired because the upload paused (chunk retries/backoff) past the credential TTL; Cloudrebve behind CDN/WAF that strips Authorization or limits body size; clock skew breaking signed URLs; server restarted mid-upload losing the session.","solutions":["Retry the whole upload (re-create the upload session) — credentials are short-lived and a stale session URL is the most common cause.","Check any WAF/CDN/nginx client_max_body_size in front of Cloudrebve allows your chunk size.","Confirm the alist host clock is synced (signed credential URLs are time-sensitive).","Inspect Cloudrebve logs for the matching request to see why the chunk endpoint rejected the request."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := upChunk(ctx, url, credential, data); err != nil {\n    if strings.HasPrefix(err.Error(), \"4\") || strings.Contains(err.Error(), \"Gone\") {\n        // credential/session likely expired: recreate the upload session once\n        session, serr := d.createUploadSession(...)\n        if serr == nil { return upChunk(ctx, session.URL, session.Credential, data) }\n    }\n    return err\n}","preventionTips":["Complete uploads promptly — chunk credentials are short-lived","Keep host clock NTP-synced for signed URLs","Ensure proxies allow the chunk PUT body size"],"tags":["cloudreve","upload","http-status","credentials","go"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}