plandex-ai/plandex · error

Error parsing request body

Error message

Error parsing request body

What it means

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.

Source

Thrown at app/server/handlers/plans_versions.go:112

	log.Println("planId: ", planId)

	if authorizePlan(w, planId, auth) == nil {
		return
	}

	// 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.RewindPlanRequest
	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
	}

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

	err = db.ExecRepoOperation(db.ExecRepoOperationParams{
		OrgId:    auth.OrgId,
		UserId:   auth.User.Id,
		PlanId:   planId,
		Branch:   branch,
		Reason:   "rewind plan",
		Scope:    db.LockScopeWrite,
		Ctx:      ctx,
		CancelFn: cancel,
	}, func(repo *db.GitRepo) error {
		return repo.GitRewindToSha(branch, requestBody.Sha)
	})

View on GitHub (pinned to e2d772072e)

Solutions

  1. Validate the payload is well-formed JSON (jq . body.json).
  2. Match the exact field names/types of shared.RewindPlanRequest (check the version your server deploys).
  3. Send header 'Content-Type: application/json'.
  4. Log/echo the parse error client-side during development to see the exact offset.

Example fix

// before
curl -X POST $API/plans/rewind -d 'planId=abc&commit=def'  // form-encoded, not JSON
// after
curl -X POST $API/plans/rewind -H 'Content-Type: application/json' -d '{"planId":"abc","commit":"def"}'
Defensive patterns

Strategy: validation

Validate before calling

// validate JSON shape before sending
payload, err := json.Marshal(shared.RewindPlanRequest{PlanId: planId, Commit: commit})
if err != nil { return err }
var check shared.RewindPlanRequest
if err := json.Unmarshal(payload, &check); err != nil {
    return fmt.Errorf("payload does not round-trip as RewindPlanRequest: %w", err)
}

Type guard

func isValidRewindRequest(b []byte) bool {
    var req shared.RewindPlanRequest
    return json.Unmarshal(b, &req) == nil
}

Try / catch

resp, err := postJSON(rewindURL, payload)
if err != nil {
    if resp != nil && resp.StatusCode == 400 && bodyContains(resp, "Error parsing request body") {
        return fmt.Errorf("rewind payload malformed: send JSON matching shared.RewindPlanRequest")
    }
    return err
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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