{"record":{"id":"0e13ee43ef780095","repo":"plandex-ai/plandex","slug":"error-reading-request-body-0e13ee","errorCode":null,"errorMessage":"Error reading request body: ","messagePattern":"Error reading request body: ","errorType":"http","errorClass":"http","httpStatus":500,"severity":"error","filePath":"app/server/handlers/sessions.go","lineNumber":25,"sourceCode":"\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"plandex-server/db\"\n\t\"plandex-server/email\"\n\t\"strings\"\n\n\tshared \"plandex-shared\"\n)\n\nfunc CreateEmailVerificationHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for CreateEmailVerificationHandler\")\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: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tvar req shared.CreateEmailVerificationRequest\n\terr = json.Unmarshal(body, &req)\n\tif err != nil {\n\t\tlog.Printf(\"Error unmarshalling request: %v\\n\", err)\n\t\thttp.Error(w, \"Error unmarshalling request: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\treq.Email = strings.ToLower(req.Email)\n\n\tvar hasAccount bool\n\tif req.UserId == \"\" {\n\t\tuser, err := db.GetUserByEmail(req.Email)\n\n\t\tif err != nil {\n\t\t\tlog.Printf(\"Error getting user: %v\\n\", err)","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/sessions.go#L7-L43","documentation":"CreateEmailVerificationHandler in sessions.go reads the entire request body with io.ReadAll(r.Body) before JSON-decoding it. When that read fails it returns 500 with \"Error reading request body: <err>\". This is an I/O-level failure while consuming the client's request stream, not a JSON formatting problem.","triggerScenarios":"The HTTP client aborts/disconnects while the server is still reading the request body; a reverse proxy truncates the body; the body exceeds a server-side limit (e.g. http.MaxBytesReader wrapping r.Body) causing a read error; TLS/connection reset mid-upload.","commonSituations":"Flaky mobile/CLI network dropping mid-request; client sends Content-Length larger than the actual body then closes; a proxy with a small request-body timeout; requests to the email-verification endpoint made with curl/clients that hang up early on redirects.","solutions":["Retry the request from the client with a stable connection and the full JSON body (application/json, correct Content-Length).","If behind a proxy (nginx/ALB), raise client_max_body_size / body timeout limits and check proxy error logs for truncation.","If a MaxBytesReader is in use, send a smaller body — this endpoint only needs email/userId flags, not large payloads.","Check the server log line accompanying the 500 for the wrapped error (unexpected EOF vs connection reset) to identify client abort vs proxy truncation."],"exampleFix":"// before (client)\nhttp.Post(url, \"application/json\", nil) // empty body, mismatched Content-Length\n// after\nbody := []byte(`{\"email\":\"user@example.com\",\"requireUser\":true}`)\nhttp.Post(url, \"application/json\", bytes.NewReader(body))","handlingStrategy":"validation","validationCode":"// client-side check before calling the endpoint\npayload, _ := json.Marshal(req)\nif len(payload) == 0 {\n    return errors.New(\"refusing to send empty request body\")\n}\nhttpReq, _ := http.NewRequest(http.MethodPost, url, bytes.NewReader(payload))\nhttpReq.Header.Set(\"Content-Type\", \"application/json\")\nhttpReq.ContentLength = int64(len(payload))","typeGuard":null,"tryCatchPattern":"// Go client: wrap the call and distinguish transport-level failures worth retrying\nresp, err := client.Do(httpReq)\nif err != nil {\n    if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, syscall.ECONNRESET) {\n        return retryWithBackoff(httpReq)\n    }\n    return fmt.Errorf(\"request body failed to send: %w\", err)\n}","preventionTips":["Always send a fully materialized body (bytes.Reader) with an accurate Content-Length.","Set Content-Type: application/json on every call to this endpoint.","Avoid cancelling the request or closing the client while the body is still uploading.","Check proxy (nginx/ALB) body size and timeout limits before deploying behind one.","On \"unexpected EOF\" in server logs, suspect client abort first and retry from a stable network."],"tags":["go","http","request-body","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-12T22:17:10.623Z"}