{"record":{"id":"534e6f8a8640b7b3","repo":"plandex-ai/plandex","slug":"error-parsing-request-body-534e6f","errorCode":null,"errorMessage":"Error parsing request body","messagePattern":"Error parsing request body","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"app/server/handlers/plans_versions.go","lineNumber":112,"sourceCode":"\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,\n\t\tReason:   \"rewind plan\",\n\t\tScope:    db.LockScopeWrite,\n\t\tCtx:      ctx,\n\t\tCancelFn: cancel,\n\t}, func(repo *db.GitRepo) error {\n\t\treturn repo.GitRewindToSha(branch, requestBody.Sha)\n\t})\n","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_versions.go#L94-L130","documentation":"After successfully reading the body, RewindPlanHandler unmarshals it into shared.RewindPlanRequest. Invalid JSON yields a 400 with 'Error parsing request body'. The server read the bytes fine, but they are not a valid RewindPlanRequest JSON document.","triggerScenarios":"json.Unmarshal(body, &requestBody) fails at plans_versions.go:112 — malformed JSON, wrong Content-Type payload, or fields with types that do not match shared.RewindPlanRequest (e.g., string where an int is expected).","commonSituations":"Sending form data or plain text instead of JSON, missing quotes/trailing commas from hand-built payloads, SDK version drift where RewindPlanRequest fields were renamed or retyped.","solutions":["Validate the payload is well-formed JSON (jq . body.json).","Match the exact field names/types of shared.RewindPlanRequest (check the version your server deploys).","Send header 'Content-Type: application/json'.","Log/echo the parse error client-side during development to see the exact offset."],"exampleFix":"// before\ncurl -X POST $API/plans/rewind -d 'planId=abc&commit=def'  // form-encoded, not JSON\n// after\ncurl -X POST $API/plans/rewind -H 'Content-Type: application/json' -d '{\"planId\":\"abc\",\"commit\":\"def\"}'","handlingStrategy":"validation","validationCode":"// validate JSON shape before sending\npayload, err := json.Marshal(shared.RewindPlanRequest{PlanId: planId, Commit: commit})\nif err != nil { return err }\nvar check shared.RewindPlanRequest\nif err := json.Unmarshal(payload, &check); err != nil {\n    return fmt.Errorf(\"payload does not round-trip as RewindPlanRequest: %w\", err)\n}","typeGuard":"func isValidRewindRequest(b []byte) bool {\n    var req shared.RewindPlanRequest\n    return json.Unmarshal(b, &req) == nil\n}","tryCatchPattern":"resp, err := postJSON(rewindURL, payload)\nif err != nil {\n    if resp != nil && resp.StatusCode == 400 && bodyContains(resp, \"Error parsing request body\") {\n        return fmt.Errorf(\"rewind payload malformed: send JSON matching shared.RewindPlanRequest\")\n    }\n    return err\n}","preventionTips":["Always send Content-Type: application/json","Validate payloads with a JSON schema or round-trip unmarshal in tests","Keep client structs in sync with shared.RewindPlanRequest field names/types","Never send form-encoded or HTML content to JSON API routes"],"tags":["http","json","go","validation"],"backgroundTag":"invalid-json-in-request","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"}