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

  1. Inspect the wrapped marshal error in the server log — it names the offending type/value
  2. Review any custom MarshalJSON methods on CreatePlanResponse or its fields for recursion or invalid output
  3. Revert or fix the recently changed field on shared.CreatePlanResponse; plain string fields like Id/Name cannot fail to marshal
  4. 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

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


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