plandex-ai/plandex · warning

Error parsing request body

Error message

Error parsing request body

What it means

ApplyPlanHandler read the body but json.Unmarshal(body, &requestBody) failed to parse it into shared.ApplyPlanRequest, returning HTTP 400 'Error parsing request body'. The payload is not valid JSON or its fields do not match the struct.

Source

Thrown at app/server/handlers/plans_changes.go:138

	if plan == nil {
		return
	}

	var err error

	// read the request body
	body, err := io.ReadAll(r.Body)
	if err != nil {
		log.Printf("Error reading request body: %v\n", err)
		http.Error(w, "Error reading request body", http.StatusInternalServerError)
		return
	}
	defer r.Body.Close()

	var requestBody shared.ApplyPlanRequest
	if err := json.Unmarshal(body, &requestBody); err != nil {
		log.Printf("Error parsing request body: %v\n", err)
		http.Error(w, "Error parsing request body", http.StatusBadRequest)
		return
	}

	// Just in case this was sent immediately after a stream finished, wait a little before locking to allow for cleanup
	time.Sleep(100 * time.Millisecond)

	ctx, cancel := context.WithCancel(r.Context())

	var settings *shared.PlanSettings
	var currentPlanParams db.CurrentPlanStateParams
	var currentPlan *shared.CurrentPlanState

	err = db.ExecRepoOperation(db.ExecRepoOperationParams{
		OrgId:    auth.OrgId,
		UserId:   auth.User.Id,
		PlanId:   planId,
		Branch:   branch,
		Scope:    db.LockScopeRead,

View on GitHub (pinned to e2d772072e)

Solutions

  1. Send a valid JSON object matching ApplyPlanRequest (e.g. {"sessionId": "...", "apiKeys": {...}}) with Content-Type: application/json
  2. Print the raw body client-side before sending to confirm it is intact JSON
  3. Align client and server plandex-shared versions so the request struct matches
  4. Avoid shell interpolation of JSON; use @file or a proper HTTP client

Example fix

// before
http.post(url, 'sessionId=' + id) // form-encoded
// after
http.post(url, JSON.stringify({sessionId: id}), {headers: {'Content-Type': 'application/json'}})
Defensive patterns

Strategy: validation

Validate before calling

const payload = {sessionId, apiKeys, openAIOrgId, authVars};
const raw = JSON.stringify(payload);
JSON.parse(raw); // fail fast locally before the request

Type guard

function isApplyPlanRequest(v) {
  return typeof v === 'object' && v !== null &&
    (v.sessionId === undefined || typeof v.sessionId === 'string') &&
    (v.apiKeys === undefined || typeof v.apiKeys === 'object');
}

Try / catch

const res = await fetch(applyUrl, opts);
if (res.status === 400 && (await res.text()).includes('Error parsing request body')) {
  // body was not valid ApplyPlanRequest JSON — inspect and fix payload
}

Prevention

When it happens

Trigger: Body is not JSON (HTML error page captured, empty body, multipart form); fields have wrong types (e.g. sessionId as number); sending apiKeys as a string instead of object.

Common situations: Client posting form-encoded data instead of JSON; a gateway returning an error page body that gets re-posted; API version mismatch where ApplyPlanRequest fields changed; shell quoting stripping JSON braces.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/f1cbeeee3a9a5c85. Report an issue: GitHub.