plandex-ai/plandex · error

Error parsing request body

Error message

Error parsing request body

What it means

CreateProjectHandler unmarshals the read body into shared.CreateProjectRequest; on JSON parse failure it returns 400 with 'Error parsing request body'. The body arrived intact but is not valid JSON for the CreateProjectRequest shape (a follow-up 'name field is required' 400 covers valid JSON with an empty name).

Source

Thrown at app/server/handlers/projects.go:37

	auth := Authenticate(w, r, true)
	if 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.CreateProjectRequest
	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
	}

	if requestBody.Name == "" {
		log.Println("Received empty name field")
		http.Error(w, "name field is required", http.StatusBadRequest)
		return
	}

	var projectId string
	err = db.WithTx(r.Context(), "create project", func(tx *sqlx.Tx) error {
		var err error

		projectId, err = db.CreateProject(auth.OrgId, requestBody.Name, tx)

		if err != nil {
			log.Printf("Error creating project: %v\n", err)
			return fmt.Errorf("error creating project: %v", err)

View on GitHub (pinned to e2d772072e)

Solutions

  1. Confirm the payload parses: jq . payload.json.
  2. Send 'Content-Type: application/json' with a raw JSON object body, not a stringified-string or form fields.
  3. Align field names/types with the shared.CreateProjectRequest struct of the deployed server.
  4. If behind a proxy, verify the API route is not intercepted by an auth/login HTML redirect.

Example fix

// before
fetch(url, {method:'POST', body: new URLSearchParams({name:'proj'})})  // form-encoded
// after
fetch(url, {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({name:'proj'})})
Defensive patterns

Strategy: validation

Validate before calling

// validate before POST /projects
if name == "" { return errors.New("name is required") }
payload, err := json.Marshal(shared.CreateProjectRequest{Name: name})
if err != nil { return err }
var check shared.CreateProjectRequest
if json.Unmarshal(payload, &check) != nil { return errors.New("payload is not valid CreateProjectRequest JSON") }

Type guard

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

Try / catch

resp, err := postJSON(projectsURL, payload)
if err != nil {
    if resp != nil && resp.StatusCode == 400 && bodyContains(resp, "Error parsing request body") {
        return fmt.Errorf("create-project payload must be JSON with a 'name' field")
    }
    return err
}

Prevention

When it happens

Trigger: json.Unmarshal(body, &requestBody) fails at projects.go:37 — malformed JSON, HTML error pages forwarded by a proxy, or mismatched field types versus shared.CreateProjectRequest.

Common situations: Posting FormData/multipart instead of JSON, double-encoding the JSON string, an auth redirect returning an HTML page to the API route, or client/server schema version mismatch.

Related errors


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