{"record":{"id":"9ae9928e6df9fff9","repo":"plandex-ai/plandex","slug":"error-marshalling-result-v","errorCode":null,"errorMessage":"error marshalling result: %v","messagePattern":"error marshalling result: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/result_helpers.go","lineNumber":33,"sourceCode":"\t\"time\"\n\n\tshared \"plandex-shared\"\n\n\t\"github.com/google/uuid\"\n)\n\nfunc StorePlanResult(result *PlanFileResult) error {\n\tnow := time.Now()\n\tif result.Id == \"\" {\n\t\tresult.Id = uuid.New().String()\n\t\tresult.CreatedAt = now\n\t}\n\tresult.UpdatedAt = now\n\n\tbytes, err := json.MarshalIndent(result, \"\", \"  \")\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error marshalling result: %v\", err)\n\t}\n\n\tresultsDir := getPlanResultsDir(result.OrgId, result.PlanId)\n\n\terr = os.MkdirAll(resultsDir, 0755)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating results dir: %v\", err)\n\t}\n\n\tlog.Printf(\"Storing plan result: %s - %s\", result.Path, result.Id)\n\n\terr = os.WriteFile(filepath.Join(resultsDir, result.Id+\".json\"), bytes, 0644)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error writing result file: %v\", err)\n\t}\n","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/result_helpers.go#L15-L51","documentation":"StorePlanResult persists a plan result by marshalling it to indented JSON before writing to the plan results directory. If json.MarshalIndent fails — which should be nearly impossible for plain result structs but can happen with unsupported types (channels, funcs, cyclic references, custom MarshalJSON errors) — the error is wrapped with this message and nothing is written.","triggerScenarios":"The result struct (or nested fields) contains values JSON cannot encode, or a field's custom MarshalJSON method returns an error; result.UpdatedAt was just set so the failure comes from other fields.","commonSituations":"Adding a field of type chan/func/complex to the Result struct; embedding a map with non-string keys (pre-Go1.7 style) or a value that fails marshalling; injecting metrics objects holding unencodable runtime values.","solutions":["Find the offending field: temporarily marshal with json.Marshal and inspect the wrapped error's field path","Remove or convert unsupported field types (chan, func, complex) to encodable representations","Add json:\"-\" tags to internal/runtime-only fields that shouldn't be serialized","Register a custom Marshaler or pre-sanitize nested payloads before StorePlanResult"],"exampleFix":"// before\ntype PlanResult struct {\n\tCallbacks map[int]func() `json:\"callbacks\"` // unencodable\n\tUpdatedAt time.Time\n}\n// after\ntype PlanResult struct {\n\tCallbacks map[int]func() `json:\"-\"` // excluded from JSON\n\tUpdatedAt time.Time\n}","handlingStrategy":"validation","validationCode":"// pre-validate the payload encodes before calling StorePlanResult\nif _, err := json.Marshal(result); err != nil {\n\treturn fmt.Errorf(\"plan result not JSON-encodable: %w\", err)\n}\nerr := StorePlanResult(result)","typeGuard":"func jsonEncodable(v any) bool {\n\tvar ok bool\n\tfunc() {\n\t\tdefer func() { if recover() != nil { ok = false } }()\n\t\t_, err := json.Marshal(v)\n\t\tok = err == nil\n\t}()\n\treturn ok\n}","tryCatchPattern":"err := StorePlanResult(result)\nif err != nil {\n\tif strings.Contains(err.Error(), \"error marshalling result\") {\n\t\tlog.Printf(\"unsupported field in PlanResult: %v\", err)\n\t\t// fall back to a sanitized copy\n\t\treturn StorePlanResult(sanitizeForJSON(result))\n\t}\n\treturn err\n}","preventionTips":["Add json:\"-\" tags to any chan/func/runtime-only struct fields","Add a unit test that marshals a fully-populated PlanResult","Avoid map keys that are not strings in serializable structs","Sanitize third-party payloads before embedding them in results"],"tags":["json","serialization","go"],"backgroundTag":"json-unsupported-type","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"}