gastownhall/beads · error

failed to marshal issue %s: %w

Error message

failed to marshal issue %s: %w

What it means

While writing the backup, each polluted issue is serialized with json.Marshal before being appended as a JSONL line. If marshaling a particular issue fails, backupPollutedIssues returns this error naming the issue ID. With standard issue structs this is rare and usually indicates an unsupported value embedded in the issue (e.g. a channel, func, or cyclic field).

Source

Thrown at cmd/bd/detect_pollution.go:112

	}

	return results
}

func backupPollutedIssues(polluted []pollutionResult, path string) error {
	// Create backup file
	// nolint:gosec // G304: path is provided by user as explicit backup location
	file, err := os.Create(path)
	if err != nil {
		return fmt.Errorf("failed to create backup file: %w", err)
	}
	defer file.Close()

	// Write each issue as JSONL
	for _, p := range polluted {
		data, err := json.Marshal(p.issue)
		if err != nil {
			return fmt.Errorf("failed to marshal issue %s: %w", p.issue.ID, err)
		}

		if _, err := file.WriteString(string(data) + "\n"); err != nil {
			return fmt.Errorf("failed to write issue %s: %w", p.issue.ID, err)
		}
	}

	return nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Identify the offending issue ID from the message and inspect it with 'bd show <id>' or direct DB access.
  2. Fix or remove the malformed issue so it can be serialized (edit and re-save it).
  3. Check for schema/version mismatch between the bd binary and the database; upgrade or run migration.
  4. If caused by a code change to types.Issue, add a MarshalJSON or json tag fix for the unsupported field.

Example fix

// before: unsupported field
Custom chan int `json:"custom"`
// after: remove or give it a JSON-safe representation
Custom string `json:"custom,omitempty"`
Defensive patterns

Strategy: validation

Validate before calling

// probe-serialize issues before committing to the backup run
for _, p := range polluted {
    if _, err := json.Marshal(p.issue); err != nil {
        fmt.Printf("issue %s will fail backup: %v\n", p.issue.ID, err)
    }
}

Try / catch

if _, err := json.Marshal(p.issue); err != nil {
    log.Printf("skipping unmarshalable issue %s: %v", p.issue.ID, err)
    continue
}

Prevention

When it happens

Trigger: os.Create succeeded but json.Marshal(p.issue) returns an error for a specific issue — typically a corrupted or non-serializable field in the stored issue data, or a struct field type unsupported by encoding/json.

Common situations: Database contains an issue written by an older/incompatible schema whose fields no longer marshal; custom field values inserted directly into storage; third-party types lacking MarshalJSON injected into the issue struct.

Related errors


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