{"record":{"id":"f3022b5b8cd076d1","repo":"gastownhall/beads","slug":"encoding-json-v","errorCode":null,"errorMessage":"encoding JSON: %v","messagePattern":"encoding JSON: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/output.go","lineNumber":50,"sourceCode":"// metadata. When BD_JSON_ENVELOPE=1 and p is non-nil, the envelope gains a\n// \"pagination\" key so programmatic consumers can detect truncation without\n// parsing stderr. When the envelope is not active, p is ignored and the\n// existing stderr text hint handles the human/text path.\nfunc outputJSONWithPagination(v interface{}, p *PaginationMeta) error {\n\tvar out interface{}\n\tif jsonEnvelopeEnabled() && p != nil {\n\t\tout = map[string]interface{}{\n\t\t\t\"schema_version\": JSONSchemaVersion,\n\t\t\t\"data\":           v,\n\t\t\t\"pagination\":     p,\n\t\t}\n\t} else {\n\t\tout = wrapWithSchemaVersion(v)\n\t}\n\tencoder := json.NewEncoder(os.Stdout)\n\tencoder.SetIndent(\"\", \"  \")\n\tif err := encoder.Encode(out); err != nil {\n\t\treturn fmt.Errorf(\"encoding JSON: %v\", err)\n\t}\n\n\tif !jsonEnvelopeEnabled() {\n\t\temitEnvelopeDeprecation()\n\t}\n\treturn nil\n}\n\nfunc outputJSONRaw(v interface{}) error {\n\tencoder := json.NewEncoder(os.Stdout)\n\tencoder.SetIndent(\"\", \"  \")\n\tif err := encoder.Encode(v); err != nil {\n\t\treturn fmt.Errorf(\"encoding JSON: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc wrapWithSchemaVersion(v interface{}) interface{} {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/output.go#L32-L68","documentation":"outputJSONWithPagination encodes the command result (optionally schema-version-wrapped) to stdout with a JSON encoder. If json.Encoder.Encode fails — practically only when the value contains unencodable data (channels, funcs, cycles, NaN/Inf in raw structs) or stdout write fails (broken pipe/ENOSPC) — it returns 'encoding JSON: %v'.","triggerScenarios":"encoder.Encode(out) errors inside outputJSONWithPagination (called by outputJSON, runReadyProxiedList, anonymous callers) — typically stdout closed/EPIPE (e.g. `bd ready --json | head`) or a result type containing unsupported values.","commonSituations":"Piping bd JSON output into `head` or a command that exits early and closes the pipe; disk full; a command embedding a non-serializable value in its result struct.","solutions":["Avoid truncating consumers: use `head -c` alternatives or ignore SIGPIPE, or check that downstream commands keep stdout open.","Check the %v cause: EPIPE means the consumer closed the pipe; ENOSPC means free disk space.","If it's an unencodable value bug, report/fix the command so its output struct is JSON-safe.","Redirect output to a file instead of a short-lived pipe."],"exampleFix":"// before\nbd ready --json | head -5       # head exits, Encode gets EPIPE\n// after\nbd ready --json > ready.json && head -5 ready.json","handlingStrategy":"try-catch","validationCode":"// ensure only JSON-encodable values reach outputJSONWithPagination\n// (no channels, funcs, cycles; sanitize NaN/Inf floats beforehand)","typeGuard":"func jsonSafe(v interface{}) bool {\n    _, err := json.Marshal(v)\n    return err == nil\n}","tryCatchPattern":"if err := outputJSONWithPagination(v, page); err != nil {\n    if errors.Is(err, syscall.EPIPE) || strings.Contains(err.Error(), \"broken pipe\") {\n        return nil // consumer closed stdout; not a real failure\n    }\n    return fmt.Errorf(\"emitting JSON output: %w\", err)\n}","preventionTips":["Avoid piping --json output into commands that exit early (head)","Redirect to files when chaining commands","Keep result structs JSON-serializable","Handle EPIPE gracefully in CLI writers"],"tags":["go","json","encoding","stdout"],"backgroundTag":"json-encode-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}