gastownhall/beads · error
failed to insert comment for %s: %w
Error message
failed to insert comment for %s: %w
What it means
PersistComments stamps each structured comment with a timestamp via NextLiveCommentTime so comments created in the same second as the issue's newest comment still order deterministically. If querying/advancing that timestamp fails (a database error from the underlying time query), the comment insert is aborted and the error is wrapped with the issue ID. The whole create transaction's comment persistence stops at that point.
Source
Thrown at internal/storage/issueops/create.go:800
var result CreateIssueResult
if len(issue.Comments) == 0 {
return result, nil
}
commentTable := "comments"
if IsWisp(issue) {
commentTable = "wisp_comments"
}
for _, comment := range issue.Comments {
createdAt := comment.CreatedAt
if createdAt.IsZero() {
// No supplied timestamp: this is a live comment, so stamp it the
// same way AddIssueComment does — one second past the issue's
// newest comment when the clock second would collide. Otherwise
// several such comments in one create share a second and read back
// in content-digest order rather than the order they were listed.
stamped, err := NextLiveCommentTime(ctx, tx, commentTable, issue.ID, time.Now())
if err != nil {
return result, fmt.Errorf("failed to insert comment for %s: %w", issue.ID, err)
}
createdAt = stamped
}
createdAtText := FormatAuxTime(createdAt)
if comment.ID == "" {
// No incoming id (fresh comment): content-derived id, collapsing
// onto an identical existing row exactly like the import dedup.
id, existed, err := InsertDerivedComment(ctx, tx, commentTable, issue.ID, comment.Author, comment.Text, createdAtText)
if err != nil {
return result, fmt.Errorf("failed to insert comment for %s: %w", issue.ID, err)
}
comment.ID = id
if !existed {
result.markChanged(commentTable)
result.persistedComments = append(result.persistedComments, EventComment{
ID: id, Author: comment.Author, Text: comment.Text, CreatedAt: createdAt, Source: CommentSourceStructured,
})
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error (%w) for the underlying DB failure (locked DB, no such table, ctx deadline) and fix that root cause.
- Retry the create once the database is reachable/locks are released.
- Verify the comment table schema matches the expected migration version (run the repo's schema migration/doctor).
- Increase the context timeout when creating issues with many comments in one transaction.
Example fix
// before ctx := context.Background() // no deadline control; large create times out result, err := issueops.CreateIssueInTxWithResult(ctx, tx, issue, opts) // after ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() result, err := issueops.CreateIssueInTxWithResult(ctx, tx, issue, opts)
Defensive patterns
Strategy: retry
Validate before calling
// verify DB reachable and comment table present before create
if err := tx.PingContext(ctx); err != nil { return err }
var n int
if err := tx.QueryRowContext(ctx,
"SELECT COUNT(*) FROM sqlite_master WHERE name = 'issue_comments'").Scan(&n); err != nil || n == 0 {
return fmt.Errorf("comment table missing; run migrations")
} Try / catch
result, err := issueops.CreateIssueInTxWithResult(ctx, tx, issue, opts)
if err != nil && strings.Contains(err.Error(), "failed to insert comment") {
if isTransient(err) { // locked / connection reset / deadline
return retryWithBackoff(ctx, func() error {
_, e := issueops.CreateIssueInTxWithResult(ctx, tx, issue, opts)
return e
})
}
return err
} Prevention
- Set generous context timeouts for creates with many comments.
- Keep the schema migrated to the current version.
- Retry transient DB errors with backoff.
- Monitor DB health (locks, disk space) before bulk operations.
When it happens
Trigger: Creating an issue with structured comments via CreateIssueInTxWithResult when NextLiveCommentTime's query against the comment table fails — e.g. the comment table is missing/corrupt, the connection dropped mid-transaction, or the context was cancelled.
Common situations: Database locked or unavailable during bulk import; schema migration mismatch leaving an old comment table; ctx timeout expiring during a large multi-comment create; disk-full or I/O errors on the embedded Dolt database.
Related errors
- comment counts: %w
- failed to check comment existence for %s: %w
- ErrExec
- database not available: %w
- no database connection
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/18d9cdf59375b03b.
Report an issue: GitHub.