gastownhall/beads · error
encoding JSON: %v
Error message
encoding JSON: %v
What it means
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'.
Source
Thrown at cmd/bd/output.go:50
// metadata. When BD_JSON_ENVELOPE=1 and p is non-nil, the envelope gains a
// "pagination" key so programmatic consumers can detect truncation without
// parsing stderr. When the envelope is not active, p is ignored and the
// existing stderr text hint handles the human/text path.
func outputJSONWithPagination(v interface{}, p *PaginationMeta) error {
var out interface{}
if jsonEnvelopeEnabled() && p != nil {
out = map[string]interface{}{
"schema_version": JSONSchemaVersion,
"data": v,
"pagination": p,
}
} else {
out = wrapWithSchemaVersion(v)
}
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
if err := encoder.Encode(out); err != nil {
return fmt.Errorf("encoding JSON: %v", err)
}
if !jsonEnvelopeEnabled() {
emitEnvelopeDeprecation()
}
return nil
}
func outputJSONRaw(v interface{}) error {
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
if err := encoder.Encode(v); err != nil {
return fmt.Errorf("encoding JSON: %v", err)
}
return nil
}
func wrapWithSchemaVersion(v interface{}) interface{} {View on GitHub (pinned to 71377f2769)
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.
Example fix
// before bd ready --json | head -5 # head exits, Encode gets EPIPE // after bd ready --json > ready.json && head -5 ready.json
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure only JSON-encodable values reach outputJSONWithPagination // (no channels, funcs, cycles; sanitize NaN/Inf floats beforehand)
Type guard
func jsonSafe(v interface{}) bool {
_, err := json.Marshal(v)
return err == nil
} Try / catch
if err := outputJSONWithPagination(v, page); err != nil {
if errors.Is(err, syscall.EPIPE) || strings.Contains(err.Error(), "broken pipe") {
return nil // consumer closed stdout; not a real failure
}
return fmt.Errorf("emitting JSON output: %w", err)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ExternalDoltConfig: must set Socket or (Host, Port)
- failed to parse backup state: %w
- failed to marshal backup state: %w
- failed to marshal issue %s: %w
- failed to load config: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f3022b5b8cd076d1.
Report an issue: GitHub.