gastownhall/beads · error

failed to check comment existence for %s: %w

Error message

failed to check comment existence for %s: %w

What it means

For comments that carry an explicit ID, PersistComments first runs a COUNT query to check whether an identical comment row (same issue_id, author, created_at, text) already exists; if the query itself fails, the error is wrapped as 'failed to check comment existence'. This is a read-failure path, not a duplicate-detection error — duplicates found this way are silently skipped (continue).

Source

Thrown at internal/storage/issueops/create.go:829

			}
			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,
				})
			}
			continue
		}
		// Incoming id (import/interchange): preserve it, with the historical
		// existence check preventing duplicates on re-import.
		var exists int
		//nolint:gosec // G201: table is determined by ephemeral flag
		if err := tx.QueryRowContext(ctx, fmt.Sprintf(`
				SELECT COUNT(*) FROM %s
				WHERE issue_id = ? AND author = ? AND created_at = ? AND text = ?
			`, commentTable), issue.ID, comment.Author, createdAtText, comment.Text).Scan(&exists); err != nil {
			return result, fmt.Errorf("failed to check comment existence for %s: %w", issue.ID, err)
		}
		if exists > 0 {
			continue
		}
		//nolint:gosec // G201: table is determined by ephemeral flag
		_, err := tx.ExecContext(ctx, fmt.Sprintf(`
			INSERT INTO %s (id, issue_id, author, text, created_at)
			VALUES (?, ?, ?, ?, ?)
		`, commentTable), comment.ID, issue.ID, comment.Author, comment.Text, createdAtText)
		if err != nil {
			return result, fmt.Errorf("failed to insert comment for %s: %w", issue.ID, err)
		}
		result.markChanged(commentTable)
		result.persistedComments = append(result.persistedComments, EventComment{
			ID: comment.ID, Author: comment.Author, Text: comment.Text, CreatedAt: createdAt, Source: CommentSourceStructured,
		})
	}
	return result, nil

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped %w error for the SQL failure mode and fix the root cause (connection, schema, timeout).
  2. Run schema initialization/migrations so the comment table exists with the expected columns.
  3. Retry with a longer-lived context; keep transactions small enough to finish within deadlines.
  4. Verify DB health (bd doctor / driver connectivity) before bulk create operations.

Example fix

// before
ctx, _ := context.WithTimeout(context.Background(), 2*time.Second) // too short for large import
result, err := issueops.CreateIssueInTxWithResult(ctx, tx, issue, opts)
// after
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel()
result, err := issueops.CreateIssueInTxWithResult(ctx, tx, issue, opts)
Defensive patterns

Strategy: validation

Validate before calling

var n int
err := tx.QueryRowContext(ctx,
    "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=?", commentTable).Scan(&n)
if err != nil || n == 0 {
    return fmt.Errorf("comment table %s missing; run migrations first", commentTable)
}

Try / catch

result, err := issueops.CreateIssueInTxWithResult(ctx, tx, issue, opts)
if err != nil && strings.Contains(err.Error(), "failed to check comment existence") {
    if ctx.Err() != nil { return ctx.Err() } // deadline/cancel — rerun with bigger budget
    return fmt.Errorf("comment table unreadable: %w", err)
}

Prevention

When it happens

Trigger: Creating an issue with pre-ID'd comments via CreateIssueInTxWithResult when the COUNT(*) SELECT against the comment table errors — wrong table name after schema drift, DB connection loss, cancelled context, or a corrupted comment table.

Common situations: Remote DB connection dropping mid-import; context deadline exceeded on large transactions; manual schema edits breaking the comments table; running against an uninitialized database lacking the comment table.

Related errors


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