{"record":{"id":"19b7d0c871ed4199","repo":"plandex-ai/plandex","slug":"error-marshalling-response-19b7d0","errorCode":null,"errorMessage":"Error marshalling response: ","messagePattern":"Error marshalling response: ","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/plans_crud.go","lineNumber":120,"sourceCode":"\n\tplan, err := db.CreatePlan(r.Context(), auth.OrgId, projectId, auth.User.Id, name)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error creating plan: %v\\n\", err)\n\t\thttp.Error(w, \"Error creating plan: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tresp := shared.CreatePlanResponse{\n\t\tId:   plan.Id,\n\t\tName: plan.Name,\n\t}\n\n\tbytes, err := json.Marshal(resp)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error marshalling response: %v\\n\", err)\n\t\thttp.Error(w, \"Error marshalling response: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.Write(bytes)\n\n\tlog.Printf(\"Successfully created plan: %v\\n\", plan)\n}\n\nfunc GetPlanHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for GetPlanHandler\")\n\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tvars := mux.Vars(r)\n\tplanId := vars[\"planId\"]","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_crud.go#L102-L138","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nfunc (p Plan) MarshalJSON() ([]byte, error) { return json.Marshal(p) } // infinite recursion\n// after\nfunc (p Plan) MarshalJSON() ([]byte, error) { return json.Marshal(struct{ ID string `json:\"id\"` }{ID: p.Id}) }","handlingStrategy":"try-catch","validationCode":"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) }","typeGuard":null,"tryCatchPattern":"bytes, err := json.Marshal(resp)\nif err != nil {\n\tlog.Printf(\"Error marshalling response: %v\\n\", err)\n\thttp.Error(w, \"Error marshalling response\", http.StatusInternalServerError)\n\treturn\n}\nw.Write(bytes)","preventionTips":["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"],"tags":["json","serialization","go","server-error"],"backgroundTag":"json-marshall-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}