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

  1. Inspect the wrapped scan error to find the offending column/value; fix or delete the malformed row.
  2. Re-insert or backfill NULL values into columns the scan expects non-NULL (author, text, created_at).
  3. 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

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


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