{"record":{"id":"3ea879785c324fc7","repo":"plandex-ai/plandex","slug":"error-reading-request-body-3ea879","errorCode":null,"errorMessage":"Error reading request body","messagePattern":"Error reading request body","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/plans_versions.go","lineNumber":104,"sourceCode":"\tif auth == nil {\n\t\treturn\n\t}\n\n\tvars := mux.Vars(r)\n\tplanId := vars[\"planId\"]\n\tbranch := vars[\"branch\"]\n\n\tlog.Println(\"planId: \", planId)\n\n\tif authorizePlan(w, planId, auth) == nil {\n\t\treturn\n\t}\n\n\t// read the request body\n\tbody, err := io.ReadAll(r.Body)\n\tif err != nil {\n\t\tlog.Printf(\"Error reading request body: %v\\n\", err)\n\t\thttp.Error(w, \"Error reading request body\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\tdefer r.Body.Close()\n\n\tvar requestBody shared.RewindPlanRequest\n\tif err := json.Unmarshal(body, &requestBody); err != nil {\n\t\tlog.Printf(\"Error parsing request body: %v\\n\", err)\n\t\thttp.Error(w, \"Error parsing request body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tctx, cancel := context.WithCancel(r.Context())\n\n\terr = db.ExecRepoOperation(db.ExecRepoOperationParams{\n\t\tOrgId:    auth.OrgId,\n\t\tUserId:   auth.User.Id,\n\t\tPlanId:   planId,\n\t\tBranch:   branch,","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_versions.go#L86-L122","documentation":"RewindPlanHandler reads the entire request body with io.ReadAll(r.Body) before decoding the rewind request. If the read fails (connection reset mid-upload, client disconnect, body size/transport error), the handler returns a 500 with 'Error reading request body'. This is a transport-level problem between client and server, not a JSON problem.","triggerScenarios":"io.ReadAll(r.Body) returns an error at plans_versions.go:104 — typically the client closed the connection during upload, a proxy timed out, or the request body stream was interrupted.","commonSituations":"Flaky networks or aggressive reverse-proxy timeouts (nginx proxy_read_timeout), clients aborting large rewind requests, or HTTP/2 stream resets.","solutions":["Retry the request; the failure is usually transient.","Increase proxy/gateway read timeouts and body limits (e.g., nginx proxy_read_timeout, client_max_body_size).","Ensure the client sends Content-Length or proper chunked encoding and does not abort early.","Check server logs for the underlying io error to distinguish client disconnects from infra issues."],"exampleFix":"// before\ncurl -X POST $API/plans/rewind -d @big.json --max-time 2  # aborted mid-upload\n// after\ncurl -X POST $API/plans/rewind -H 'Content-Type: application/json' --data-binary @rewind.json --max-time 30","handlingStrategy":"retry","validationCode":"// ensure body is fully available and sized before sending\npayload, _ := json.Marshal(rewindReq)\nif len(payload) == 0 || len(payload) > maxBodySize {\n    return errors.New(\"rewind payload missing or too large\")\n}","typeGuard":"func bodyReadSucceeded(err error) bool { return err == nil }","tryCatchPattern":"err := withRetry(3, func() error {\n    resp, e := http.Post(rewindURL, \"application/json\", bytes.NewReader(payload))\n    if e != nil { return e }\n    if resp.StatusCode == 500 && bodyContains(resp, \"Error reading request body\") {\n        return errRetryable // transport glitch; retry\n    }\n    return nil\n})","preventionTips":["Set generous client and proxy timeouts for rewind requests","Avoid aborting requests mid-upload (respect context deadlines)","Raise proxy body limits (nginx client_max_body_size, proxy_read_timeout)","Retry idempotent reads on 500 body-read failures"],"tags":["http","go","request-body","network"],"backgroundTag":"request-body-read-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}