{"record":{"id":"46bdc236fff219a4","repo":"gastownhall/beads","slug":"failed-to-write-json-w","errorCode":null,"errorMessage":"failed to write JSON: %w","messagePattern":"failed to write JSON: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/doctor.go","lineNumber":1118,"sourceCode":"func convertWithCategory(dc doctor.DoctorCheck, category string) doctorCheck {\n\tcheck := convertDoctorCheck(dc)\n\tcheck.Category = category\n\treturn check\n}\n\n// exportDiagnostics writes the doctor result to a JSON file\nfunc exportDiagnostics(result doctorResult, outputPath string) error {\n\t// #nosec G304 - outputPath is a user-provided flag value for file generation\n\tf, err := os.Create(outputPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create output file: %w\", err)\n\t}\n\tdefer f.Close()\n\n\tencoder := json.NewEncoder(f)\n\tencoder.SetIndent(\"\", \"  \")\n\tif err := encoder.Encode(result); err != nil {\n\t\treturn fmt.Errorf(\"failed to write JSON: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc printDiagnostics(result doctorResult) {\n\t// Pre-calculate counts and collect issues grouped by category\n\tchecksByCategory := make(map[string][]doctorCheck)\n\tissuesByCategory := make(map[string][]doctorCheck)\n\tvar passCount, warnCount, failCount int\n\thasIssues := false\n\n\tfor _, check := range result.Checks {\n\t\tcat := check.Category\n\t\tif cat == \"\" {\n\t\t\tcat = \"Other\"\n\t\t}\n\t\tchecksByCategory[cat] = append(checksByCategory[cat], check)","sourceCodeStart":1100,"sourceCodeEnd":1136,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/doctor.go#L1100-L1136","documentation":"exportDiagnostics wraps errors from the json.Encoder while marshalling and streaming the doctor result to the file. This means the doctor result structure could not be encoded to JSON (e.g. an unsupported value surfaced during encoding). It is rare because doctorResult is a plain JSON-friendly struct.","triggerScenarios":"Calling exportDiagnostics (via `bd doctor --output <file>`) when json.Encoder.Encode fails — typically a marshalling error on the doctorResult payload (unsupported type such as a channel/func field, or an invalid-number edge case) at cmd/bd/doctor.go:1118.","commonSituations":"Mostly seen during development when a new field with a non-JSON-serializable type is added to doctorResult; end users rarely hit it since the struct is static and JSON-safe. Also theoretically on write failures mid-stream to disk.","solutions":["Update bd to the latest version (this usually indicates a code bug in a newly added field)","Inspect the wrapped error message for the offending Go type and report/file an issue with bd maintainers","As a workaround, capture doctor output to stdout (omit --output) instead of writing the JSON file"],"exampleFix":"// before (adding a field to doctorResult)\nData chan struct{} `json:\"data\"`\n// after\nData []byte `json:\"data\"` // JSON-encodable type only","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := exportDiagnostics(result, outPath); err != nil {\n\tif strings.Contains(err.Error(), \"failed to write JSON\") {\n\t\tlog.Printf(\"JSON encode failed (likely a bug in bd): %v; falling back to stdout\", err)\n\t\tprintDiagnostics(result)\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Keep doctorResult fields JSON-serializable (no chan/func/cycles) when contributing code","Report persistent encode failures as bd bugs with the wrapped error text","Use stdout output as a fallback path in scripts","Keep bd updated to benefit from serialization fixes"],"tags":["json","serialization","doctor","export"],"backgroundTag":"json-encoding-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}