plandex-ai/plandex · warning
Error decoding request body
Error message
Error decoding request body
What it means
HTTP 400 error returned by UpdatePlanConfigHandler when json.NewDecoder fails to decode the request body into a shared.UpdatePlanConfigRequest. This is a client-side validation failure: the payload is not valid JSON or does not match the expected request shape. Plan authorization has already succeeded, so only the request body itself is at fault.
Source
Thrown at app/server/handlers/plan_config.go:78
if auth == nil {
return
}
vars := mux.Vars(r)
planId := vars["planId"]
log.Println("planId: ", planId)
plan := authorizePlan(w, planId, auth)
if plan == nil {
return
}
var req shared.UpdatePlanConfigRequest
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
log.Println("Error decoding request body: ", err)
http.Error(w, "Error decoding request body", http.StatusBadRequest)
return
}
err = db.StorePlanConfig(planId, req.Config)
if err != nil {
log.Println("Error storing plan config: ", err)
http.Error(w, "Error storing plan config", http.StatusInternalServerError)
return
}
log.Println("UpdatePlanConfigHandler processed successfully")
}
func GetDefaultPlanConfigHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for GetDefaultPlanConfigHandler")
auth := Authenticate(w, r, true)
if auth == nil {View on GitHub (pinned to e2d772072e)
Solutions
- Send a valid JSON body matching shared.UpdatePlanConfigRequest, e.g. {"config": {...}}
- Set header Content-Type: application/json
- Validate the JSON with a linter or jq before sending
- Check for field type mismatches against the latest shared model (client/server version skew)
- Log the raw body on the server when this 400 occurs to see what was received
Example fix
// before (curl)
curl -d config={"model":"gpt-4"} ...
// after
curl -H 'Content-Type: application/json' -d '{"config":{"model":"gpt-4"}}' ... Defensive patterns
Strategy: validation
Validate before calling
// client: validate body before sending
const body = { config: planConfig };
const json = JSON.stringify(body);
if (!json || json === '{}') throw new Error('request body required');
await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: json }); Type guard
function isUpdatePlanConfigRequest(v) {
return v != null && typeof v === 'object' && 'config' in v && typeof v.config === 'object';
} Try / catch
try {
await updatePlanConfig(planId, config);
} catch (e) {
if (e.status === 400) { /* show user 'invalid JSON body'; do not retry */ }
else throw e;
} Prevention
- Always send Content-Type: application/json
- Validate payload shape client-side against the shared schema
- Verify JSON with jq/JSON.parse before sending
- Keep client and server shared models in sync
When it happens
Trigger: POST/PUT update-plan-config with non-JSON body, trailing garbage after valid JSON, wrong field types (e.g. string where number expected), sending Content-Length > 0 with an empty body, or forgetting to close the JSON object.
Common situations: Client sending form-encoded data instead of JSON, missing Content-Type handling in scripts, older client versions posting a stale request schema, curl commands with quoting mistakes, proxy stripping the body.
Related errors
- Error parsing request body
- Invalid request body:
- Error parsing request body
- Error parsing request body
- Error parsing request body
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/758fcc5ff3b8fd53.
Report an issue: GitHub.