{"record":{"id":"7e3be38ecb59f276","repo":"plandex-ai/plandex","slug":"error-reading-request-body-7e3be3","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_crud.go","lineNumber":55,"sourceCode":"\tprojectId := vars[\"projectId\"]\n\n\tlog.Println(\"projectId: \", projectId)\n\n\tif !authorizeProject(w, projectId, auth) {\n\t\treturn\n\t}\n\n\t_, apiErr := hooks.ExecHook(hooks.WillCreatePlan, hooks.HookParams{Auth: auth})\n\tif apiErr != nil {\n\t\twriteApiError(w, *apiErr)\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.CreatePlanRequest\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\tname := requestBody.Name\n\tif name == \"\" {\n\t\tname = \"draft\"\n\t}\n\n\tif name == \"draft\" {\n\t\t// delete any existing draft plans","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_crud.go#L37-L73","documentation":"CreatePlanHandler returns this 500 when io.ReadAll(r.Body) fails while reading the raw request body. This means the body stream errored mid-read — the client disconnected, the body was truncated, or a proxy/transport error interrupted the upload. Note the response deliberately omits the underlying error detail.","triggerScenarios":"POST create-plan where the TCP connection drops during body transfer, the client aborts the request mid-upload, a reverse proxy cuts off the body, or Content-Length/malformed chunked encoding truncates the stream.","commonSituations":"Client timeouts on slow networks while sending a large body; flaky proxies/load balancers terminating connections; curl/fetch calls aborted by the caller; HTTP client sending chunked bodies through a misconfigured proxy.","solutions":["Retry the request from a stable connection","Check server/client network path and reverse proxy body-size or timeout settings","Verify the client actually sends a body and does not abort mid-write","Increase client HTTP timeout for slow links","Check server logs for connection-reset patterns at the same time"],"exampleFix":"// before\ncurl -X POST $URL/plans --max-time 1 -d name=myplan\n// after\ncurl -X POST $URL/plans --max-time 30 -H 'Content-Type: application/json' -d '{\"name\":\"myplan\"}'","handlingStrategy":"validation","validationCode":"const body = JSON.stringify({name});\nif (!navigator.onLine) throw new Error('No network connection');\nconst res = await fetch(url, {method:'POST', body, headers:{'Content-Type':'application/json'}, signal: AbortSignal.timeout(30000)});","typeGuard":null,"tryCatchPattern":"try {\n  await createPlan(projectId, name);\n} catch (e) {\n  if (/Error reading request body/.test(e.message)) {\n    // connection dropped mid-upload — retry once on a fresh connection\n    return createPlan(projectId, name);\n  }\n  throw e;\n}","preventionTips":["Set adequate client HTTP timeouts for slow networks","Keep create-plan request bodies small (name only)","Check proxy/load-balancer idle and body timeouts","Detect client aborts and retry idempotent creation attempts"],"tags":["http-500","request-body","network","io"],"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"}