plandex-ai/plandex · error

error reading request body: %v

Error message

error reading request body: %v

What it means

TellPlanHandler reads the entire HTTP request body with io.ReadAll(r.Body) before decoding it. If reading the stream fails (client disconnect, transport reset, body size issues), it logs, reports to notify, and returns HTTP 500 with 'Error reading request body'.

Source

Thrown at app/server/handlers/plans_exec.go:52

	log.Println("planId: ", planId)

	plan := authorizePlanExecUpdate(w, planId, auth)
	if plan == nil {
		return
	}

	settings, err := db.GetPlanSettings(plan)
	if err != nil {
		log.Printf("Error getting plan settings: %v\n", err)
		http.Error(w, "Error getting plan settings", http.StatusInternalServerError)
		return
	}

	body, err := io.ReadAll(r.Body)
	if err != nil {
		log.Printf("Error reading request body: %v\n", err)
		go notify.NotifyErr(notify.SeverityError, fmt.Errorf("error reading request body: %v", err))
		http.Error(w, "Error reading request body", http.StatusInternalServerError)
		return
	}
	defer func() {
		log.Println("Closing request body")
		r.Body.Close()
	}()

	var requestBody shared.TellPlanRequest
	if err := json.Unmarshal(body, &requestBody); err != nil {
		log.Printf("Error parsing request body: %v\n", err)
		go notify.NotifyErr(notify.SeverityError, fmt.Errorf("error parsing request body: %v", err))
		http.Error(w, "Error parsing request body", http.StatusBadRequest)
		return
	}

	_, apiErr := hooks.ExecHook(hooks.WillTellPlan, hooks.HookParams{
		Auth: auth,

View on GitHub (pinned to e2d772072e)

Solutions

  1. Retry the request from the client, ensuring the connection stays alive until the response arrives.
  2. Check intermediary proxy/gateway timeout settings (e.g. proxy_read_timeout) and raise them.
  3. Confirm the client sends Content-Length or valid chunked framing and doesn't abort early.
  4. Inspect gateway access logs for 499/client-abort around the failure time.

Example fix

// before
body, err := io.ReadAll(r.Body)
if err != nil { http.Error(w, "Error reading request body", http.StatusInternalServerError) }
// after
body, err := io.ReadAll(r.Body)
if err != nil {
    if errors.Is(err, context.Canceled) {
        http.Error(w, "request canceled", http.StatusRequestTimeout)
        return
    }
    http.Error(w, "Error reading request body", http.StatusInternalServerError)
}
Defensive patterns

Strategy: validation

Validate before calling

// Client side: send with proper framing and a context with adequate timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(payload))
req.Header.Set("Content-Type", "application/json")

Try / catch

body, err := io.ReadAll(r.Body)
if err != nil {
    if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
        http.Error(w, "request canceled", http.StatusRequestTimeout)
        return
    }
    http.Error(w, "Error reading request body", http.StatusInternalServerError)
    return
}

Prevention

When it happens

Trigger: The client's TCP connection drops or times out while the server is still reading the body; proxies/load balancers cut the request mid-body; request aborted via context cancellation.

Common situations: Slow uploads behind reverse proxies with aggressive idle timeouts; clients canceling requests; network instability between gateway and app.

Related errors


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