gastownhall/beads · error

failed to write JSON: %w

Error message

failed to write JSON: %w

What it means

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.

Source

Thrown at cmd/bd/doctor.go:1118

func convertWithCategory(dc doctor.DoctorCheck, category string) doctorCheck {
	check := convertDoctorCheck(dc)
	check.Category = category
	return check
}

// exportDiagnostics writes the doctor result to a JSON file
func exportDiagnostics(result doctorResult, outputPath string) error {
	// #nosec G304 - outputPath is a user-provided flag value for file generation
	f, err := os.Create(outputPath)
	if err != nil {
		return fmt.Errorf("failed to create output file: %w", err)
	}
	defer f.Close()

	encoder := json.NewEncoder(f)
	encoder.SetIndent("", "  ")
	if err := encoder.Encode(result); err != nil {
		return fmt.Errorf("failed to write JSON: %w", err)
	}

	return nil
}

func printDiagnostics(result doctorResult) {
	// Pre-calculate counts and collect issues grouped by category
	checksByCategory := make(map[string][]doctorCheck)
	issuesByCategory := make(map[string][]doctorCheck)
	var passCount, warnCount, failCount int
	hasIssues := false

	for _, check := range result.Checks {
		cat := check.Category
		if cat == "" {
			cat = "Other"
		}
		checksByCategory[cat] = append(checksByCategory[cat], check)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Update bd to the latest version (this usually indicates a code bug in a newly added field)
  2. Inspect the wrapped error message for the offending Go type and report/file an issue with bd maintainers
  3. As a workaround, capture doctor output to stdout (omit --output) instead of writing the JSON file

Example fix

// before (adding a field to doctorResult)
Data chan struct{} `json:"data"`
// after
Data []byte `json:"data"` // JSON-encodable type only
Defensive patterns

Strategy: try-catch

Try / catch

if err := exportDiagnostics(result, outPath); err != nil {
	if strings.Contains(err.Error(), "failed to write JSON") {
		log.Printf("JSON encode failed (likely a bug in bd): %v; falling back to stdout", err)
		printDiagnostics(result)
		return nil
	}
	return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/46bdc236fff219a4. Report an issue: GitHub.