plandex-ai/plandex · error
Error marshalling response:
Error message
Error marshalling response:
What it means
CreatePlanHandler returns this 500 when json.Marshal fails on the CreatePlanResponse struct. This is extremely rare for a simple {Id, Name} struct and almost always indicates a programmer error such as an invalid custom MarshalJSON implementation or a circular reference if the struct grows.
Source
Thrown at app/server/handlers/plans_crud.go:120
plan, err := db.CreatePlan(r.Context(), auth.OrgId, projectId, auth.User.Id, name)
if err != nil {
log.Printf("Error creating plan: %v\n", err)
http.Error(w, "Error creating plan: "+err.Error(), http.StatusInternalServerError)
return
}
resp := shared.CreatePlanResponse{
Id: plan.Id,
Name: plan.Name,
}
bytes, err := json.Marshal(resp)
if err != nil {
log.Printf("Error marshalling response: %v\n", err)
http.Error(w, "Error marshalling response: "+err.Error(), http.StatusInternalServerError)
return
}
w.Write(bytes)
log.Printf("Successfully created plan: %v\n", plan)
}
func GetPlanHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for GetPlanHandler")
auth := Authenticate(w, r, true)
if auth == nil {
return
}
vars := mux.Vars(r)
planId := vars["planId"]View on GitHub (pinned to e2d772072e)
Solutions
- Inspect the wrapped marshal error in the server log — it names the offending type/value
- Review any custom MarshalJSON methods on CreatePlanResponse or its fields for recursion or invalid output
- Revert or fix the recently changed field on shared.CreatePlanResponse; plain string fields like Id/Name cannot fail to marshal
- Add a unit test marshalling CreatePlanResponse to catch regressions
Example fix
// before
func (p Plan) MarshalJSON() ([]byte, error) { return json.Marshal(p) } // infinite recursion
// after
func (p Plan) MarshalJSON() ([]byte, error) { return json.Marshal(struct{ ID string `json:"id"` }{ID: p.Id}) } Defensive patterns
Strategy: try-catch
Validate before calling
if b, err := json.Marshal(resp); err != nil { log.Printf("marshal failed: %v", err); http.Error(w, "internal error", 500); return } else { w.Write(b) } Try / catch
bytes, err := json.Marshal(resp)
if err != nil {
log.Printf("Error marshalling response: %v\n", err)
http.Error(w, "Error marshalling response", http.StatusInternalServerError)
return
}
w.Write(bytes) Prevention
- Unit-test json.Marshal on every response struct when you change shared types
- Avoid custom MarshalJSON implementations unless necessary; never recurse into yourself
- Keep the shared module version in sync between services
- Return a generic message to clients; keep details in logs
When it happens
Trigger: json.Marshal(resp) returning an error — only possible if CreatePlanResponse or one of its fields implements json.Marshaler incorrectly (e.g. returning itself recursively) — triggered by every successful plan creation whose serialization then fails.
Common situations: A recent change to shared.CreatePlanResponse added a field with a buggy MarshalJSON; a custom type with infinite recursion in MarshalJSON; a nil embedded pointer dereferenced in custom marshaling code.
Related errors
- Error marshalling plan:
- error marshalling models: %v
- error marshalling model pack: %v
- error marshalling current plan settings: %v
- error marshalling convo message: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/19b7d0c871ed4199.
Report an issue: GitHub.