{"record":{"id":"175e5ba444ae8585","repo":"rancher/rancher","slug":"cannot-read-request-body-v-175e5b","errorCode":null,"errorMessage":"cannot read request body: %v","messagePattern":"cannot read request body: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"pkg/api/norman/customization/alibaba/handler.go","lineNumber":192,"sourceCode":"\t\t}\n\t\twriter.Write(serialized)\n\tcase \"alibabaImageSupportedInstanceTypes\":\n\t\tif serialized, errCode, err = describeImageSupportedInstanceTypes(capabilities, req); err != nil {\n\t\t\tlogrus.Debugf(\"[alibaba-handler] error call describeImageSupportedInstanceTypes: %v\", err)\n\t\t\tutil.ReturnHTTPError(writer, req, errCode, err.Error())\n\t\t\treturn\n\t\t}\n\t\twriter.Write(serialized)\n\tdefault:\n\t\thandleErr(writer, httperror.NotFound.Status, fmt.Errorf(\"invalid endpoint %v\", resourceType))\n\t}\n}\n\nfunc (h *handler) checkCredentials(req *http.Request) (int, error) {\n\tcred := &Capabilities{}\n\traw, err := io.ReadAll(req.Body)\n\tif err != nil {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"cannot read request body: %v\", err)\n\t}\n\n\tif err = json.Unmarshal(raw, &cred); err != nil {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"cannot parse request body: %v\", err)\n\t}\n\n\tif cred.RegionID == \"\" {\n\t\tcred.RegionID = defaultRegion\n\t}\n\tif cred.AccessKeyID == \"\" {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"must provide access key ID\")\n\t}\n\tif cred.AccessKeySecret == \"\" {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"must provide access key secret\")\n\t}\n\n\tclient, err := CreateECSClient(cred.AccessKeyID, cred.AccessKeySecret, cred.RegionID)\n\tif err != nil {","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/rancher/rancher/blob/932558d4e68565aff2d2f36e89ec4a391b06e7c5/pkg/api/norman/customization/alibaba/handler.go#L174-L210","documentation":"checkCredentials does io.ReadAll(req.Body) and returns HTTP 400 'cannot read request body: %v' when the read itself fails. The handler never got a parsable body: the connection reset mid-upload, the body was truncated by a proxy, or a size limit was enforced upstream.","triggerScenarios":"Client aborts or network reset during upload; reverse proxy (nginx client_max_body_size, Traefik limits) truncating; very large or chunked bodies the server rejects; keep-alive recycled mid-request.","commonSituations":"Flaky client networks; aggressive proxy body-size caps; load balancer idle timeouts on slow uploads.","solutions":["Retry the request - read failures are usually transient transport errors","Shrink the payload; only accessKeyId/accessKeySecret/regionId are needed","Raise proxy body-size and timeout limits on the path to Rancher","Confirm the client sends Content-Length and completes the body (no dangling chunked stream)"],"exampleFix":"// before\nawait fetch(url, {method: 'POST', body: hugeBlob}); // proxy truncates -> 400\n// after\nawait fetch(url, {\n  method: 'POST',\n  headers: {'Content-Type': 'application/json'},\n  body: JSON.stringify({accessKeyId: id, accessKeySecret: secret})\n});","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n\tconst res = await fetch(url, {method: 'POST', body: JSON.stringify(payload)});\n\tif (!res.ok) {\n\t\tconst msg = await res.text();\n\t\tif (msg.includes('cannot read request body')) {\n\t\t\t// transport truncated the upload - safe to retry once\n\t\t}\n\t}\n} catch (e) {\n\t// network-level failure before the server saw a body: retry idempotently\n}","preventionTips":["Keep credential-check bodies tiny - three string fields suffice","Check proxy body-size limits (nginx client_max_body_size) on API routes","Retry once on connection reset before reporting an error"],"tags":["alibaba","request-body","http","proxy"],"backgroundTag":null,"analyzedSha":"932558d4e68565aff2d2f36e89ec4a391b06e7c5","analyzedAt":"2026-08-16T04:37:02.125Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}