gastownhall/beads · error
get issue comments: scan: %w
Error message
get issue comments: scan: %w
What it means
GetIssueCommentsInTx fails while scanning a row into types.Comment (id, issue_id, author, text, created_at). Scan errors mean the result set does not match expectations: NULL in a NOT-NULL-expected column, a driver type mismatch, or an altered column list. Wrapped as "get issue comments: scan: %w" with the offending row context lost to the loop.
Source
Thrown at internal/storage/issueops/comments.go:39
table = "wisp_comments"
}
rows, err := tx.QueryContext(ctx, fmt.Sprintf(`
SELECT id, issue_id, author, text, created_at
FROM %s
WHERE issue_id = ?
ORDER BY created_at ASC, id ASC
`, table), issueID)
if err != nil {
return nil, fmt.Errorf("get issue comments from %s: %w", table, err)
}
defer rows.Close()
var comments []*types.Comment
for rows.Next() {
var c types.Comment
if err := rows.Scan(&c.ID, &c.IssueID, &c.Author, &c.Text, &c.CreatedAt); err != nil {
return nil, fmt.Errorf("get issue comments: scan: %w", err)
}
comments = append(comments, &c)
}
return comments, rows.Err()
}
// Comment page-read tuning. Mirrors the EventsSince keyset clamp: an unbounded
// page defeats the purpose of paging a long thread, so a non-positive limit
// falls back to the default and any larger request is capped.
const (
defaultCommentsPageLimit = 100
maxCommentsPageLimit = 500
)
// CommentsKeysetPredicate is the SARGABLE (created_at ASC, id ASC) keyset resume
// predicate GetIssueCommentsPageInTx ANDs in once a page cursor is set. Its three
// ? placeholders bind, in order: created_at (the sargable lower bound),
// created_at (strict), and id (the same-second tie-break).View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped scan error to find the offending column/value; fix or delete the malformed row.
- Re-insert or backfill NULL values into columns the scan expects non-NULL (author, text, created_at).
- If caused by a version mismatch, align the bd binary and database schema versions.
Example fix
// before (row has NULL author) // get issue comments: scan: sql: Scan error on column "author": unsupported Scan // after — repair the row UPDATE comments SET author = 'unknown' WHERE author IS NULL;
Defensive patterns
Strategy: try-catch
Try / catch
comments, err := store.GetIssueComments(ctx, id)
if err != nil {
var scanErr error
if strings.Contains(err.Error(), "scan") {
return fmt.Errorf("corrupt/legacy row in comments for %s: %w", id, err)
}
_ = scanErr
return err
} Prevention
- Never hand-edit comment rows in SQL; keep NULLs out of author/text/created_at.
- Run migrations in one step so column lists always match the binary's Scan calls.
- After restores or imports, spot-check rows scan cleanly before serving reads.
When it happens
Trigger: A row in comments has NULL author/text while the Go struct scans into string; a backend driver returning created_at as []byte/string incompatible with the scan target; someone added a column or changed a type without updating this scan.
Common situations: Rows imported/edited manually in SQL bypassing validation; mixed-version clusters where replicas have older column types; custom drivers (non-Dolt SQLite) with differing DATETIME handling.
Related errors
- search %s (id scan): scan: %w
- scan dependency source: %w
- scan dependency target: %w
- ErrScan
- failed to scan dependency keys: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/5e6c630eff412542.
Report an issue: GitHub.