{"record":{"id":"1315d0b1ac4c87ad","repo":"plandex-ai/plandex","slug":"error-reading-request-body-1315d0","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_exec.go","lineNumber":53,"sourceCode":"\tlog.Println(\"planId: \", planId)\n\n\tplan := authorizePlanExecUpdate(w, planId, auth)\n\tif plan == nil {\n\t\treturn\n\t}\n\n\tsettings, err := db.GetPlanSettings(plan)\n\tif err != nil {\n\t\tlog.Printf(\"Error getting plan settings: %v\\n\", err)\n\t\thttp.Error(w, \"Error getting plan settings\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tbody, err := io.ReadAll(r.Body)\n\tif err != nil {\n\t\tlog.Printf(\"Error reading request body: %v\\n\", err)\n\t\tgo notify.NotifyErr(notify.SeverityError, fmt.Errorf(\"error reading request body: %v\", err))\n\t\thttp.Error(w, \"Error reading request body\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\tdefer func() {\n\t\tlog.Println(\"Closing request body\")\n\t\tr.Body.Close()\n\t}()\n\n\tvar requestBody shared.TellPlanRequest\n\tif err := json.Unmarshal(body, &requestBody); err != nil {\n\t\tlog.Printf(\"Error parsing request body: %v\\n\", err)\n\t\tgo notify.NotifyErr(notify.SeverityError, fmt.Errorf(\"error parsing request body: %v\", err))\n\t\thttp.Error(w, \"Error parsing request body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\t_, apiErr := hooks.ExecHook(hooks.WillTellPlan, hooks.HookParams{\n\t\tAuth: auth,\n\t\tPlan: plan,","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_exec.go#L35-L71","documentation":"TellPlanHandler reads the whole HTTP request body with io.ReadAll before unmarshalling the TellPlanRequest. If the body stream fails mid-read (client disconnect, network reset, proxy/timeout cutting the connection), it logs the error, sends an async Sentry-style notification, and responds 500 with 'Error reading request body'. This is a transport-level failure, not a data problem.","triggerScenarios":"POST to the plan tell endpoint where r.Body cannot be fully read: client closed the connection before finishing the upload, an intermediary (load balancer, proxy) reset the stream, or the request exceeded a server/body timeout while reading.","commonSituations":"CLI client aborts with Ctrl-C mid-request; slow uploads hitting an ingress read timeout; flaky mobile/VPN connections; misconfigured proxy buffering that truncates large bodies.","solutions":["Retry the request from the client once the connection is stable; verify the client process was not killed mid-send.","Check client-side: ensure the HTTP client sends Content-Length / closes the request body correctly and does not hang on a slow network.","Inspect and raise proxy/ingress read timeouts (nginx proxy_read_timeout, ALB idle timeout) if large bodies are involved.","Check server logs for the wrapped io error (e.g. 'unexpected EOF', 'connection reset by peer') to confirm transport vs. server fault."],"exampleFix":"// before: no size/timeout guard, raw io.ReadAll\nbody, err := io.ReadAll(r.Body)\n// after: bound the read with http.MaxBytesReader and a server ReadTimeout\nr.Body = http.MaxBytesReader(w, r.Body, 10<<20)\nbody, err := io.ReadAll(r.Body)\nif err != nil {\n    http.Error(w, \"Error reading request body\", http.StatusBadRequest)\n    return\n}","handlingStrategy":"retry","validationCode":"// client-side pre-check before sending\nif len(payload) > 10<<20 { return errors.New(\"payload too large\") }\nreq, _ := http.NewRequestWithContext(ctx, \"POST\", url, bytes.NewReader(payload))\nreq.ContentLength = int64(len(payload))","typeGuard":null,"tryCatchPattern":"res, err := client.Do(req)\nif err != nil || res.StatusCode == 500 {\n    if isTransient(err, res) && attempt < 3 { time.Sleep(backoff); continue }\n    return fmt.Errorf(\"body read failed on server: %v\", err)\n}","preventionTips":["Set realistic client timeouts and avoid canceling the request context mid-send.","Keep request bodies small; stream large context instead of embedding it.","Configure proxy/ingress read timeouts larger than the client's worst-case upload time.","Monitor for 'unexpected EOF'/'connection reset' in server logs to catch network path issues early."],"tags":["http","request-body","io","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-12T22:17:10.623Z"}