gastownhall/beads · error

journal: marshal comment for %s: %w

Error message

journal: marshal comment for %s: %w

What it means

insertEventRow marshals the EventComment payload to JSON before insert; failure is wrapped as 'journal: marshal comment for %s'. Same mechanism as the issue/dep marshals but for comment events.

Source

Thrown at internal/storage/issueops/journal.go:441

		b, err := json.Marshal(issue)
		if err != nil {
			return fmt.Errorf("journal: marshal issue %s: %w", issueID, err)
		}
		issueJSON = string(b)
	}
	var depJSON any
	if dep != nil {
		b, err := json.Marshal(dep)
		if err != nil {
			return fmt.Errorf("journal: marshal dep for %s: %w", issueID, err)
		}
		depJSON = string(b)
	}
	var commentJSON any
	if comment != nil {
		b, err := json.Marshal(comment)
		if err != nil {
			return fmt.Errorf("journal: marshal comment for %s: %w", issueID, err)
		}
		commentJSON = string(b)
	}
	insert := func(seq int64) error {
		_, err := tx.ExecContext(ctx, `
			INSERT INTO bd_events_journal (seq, ts, op, issue_id, actor, issue_json, dep_json, comment_json)
			VALUES (?, ?, ?, ?, ?, ?, ?, ?)
		`, seq, time.Now().UTC(), string(op), issueID, actor, issueJSON, depJSON, commentJSON)
		return err
	}

	seq, err := nextEventSeq(ctx, tx)
	if err != nil {
		return err
	}
	if err := insert(seq); err != nil {
		// A duplicate seq means the counter is BEHIND the journal — it was
		// restored, hand-edited, or copied from another workspace. Left alone

View on GitHub (pinned to 71377f2769)

Solutions

  1. Sanitize the comment body to valid UTF-8 before adding
  2. Only attach string/JSON-native values to comment metadata
  3. Inspect the wrapped error for the exact field
  4. Upgrade the library if stock payloads fail to marshal

Example fix

// before
c := &ops.EventComment{Author: "bot", Body: string(rawBytes)} // rawBytes not UTF-8
ops.RecordCommentEventInTx(ctx, tx, id, c)
// after
c := &ops.EventComment{Author: "bot", Body: strings.ToValidUTF8(string(rawBytes), "\ufffd")}
ops.RecordCommentEventInTx(ctx, tx, id, c)
Defensive patterns

Strategy: validation

Validate before calling

if !utf8.ValidString(c.Body) {
    return errors.New("comment body must be valid UTF-8")
}
if _, err := json.Marshal(c); err != nil { return err }

Try / catch

if err := ops.RecordCommentEventInTx(ctx, tx, id, c); err != nil {
    if strings.Contains(err.Error(), "marshal comment") { return fmt.Errorf("bad comment payload: %w", err) }
    return err
}

Prevention

When it happens

Trigger: RecordCommentEventInTx with an *EventComment whose fields (body, author, metadata) cannot be JSON-encoded — typically invalid UTF-8 or unsupported nested types in comment extensions.

Common situations: Importing comments from external systems with binary bodies; bots writing non-string metadata into comment payloads; encoding mismatches from external feeds.

Related errors


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