gastownhall/beads · error
db: LabelSQLRepository.List: scan: %w
Error message
db: LabelSQLRepository.List: scan: %w
What it means
LabelSQLRepository.List failed while scanning a row from the labels table into a string. database/sql's rows.Scan returned an error for the current row, and the repository wraps it with this context. It means the query succeeded but a row could not be converted into the destination type.
Source
Thrown at internal/storage/domain/db/label.go:143
if issueID == "" {
return nil, fmt.Errorf("db: LabelSQLRepository.List: issueID must not be empty")
}
table := pickLabelTable(opts.UseWispsTable)
//nolint:gosec // G201: table is one of two hardcoded constants
rows, err := r.runner.QueryContext(ctx,
fmt.Sprintf("SELECT label FROM %s WHERE issue_id = ? ORDER BY label", table),
issueID,
)
if err != nil {
return nil, fmt.Errorf("db: LabelSQLRepository.List %s: %w", issueID, err)
}
defer rows.Close()
var out []string
for rows.Next() {
var label string
if err := rows.Scan(&label); err != nil {
return nil, fmt.Errorf("db: LabelSQLRepository.List: scan: %w", err)
}
out = append(out, label)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("db: LabelSQLRepository.List: rows: %w", err)
}
return out, nil
}
func (r *labelSQLRepositoryImpl) ListByIssueIDs(ctx context.Context, issueIDs []string, opts domain.LabelOpts) (map[string][]string, error) {
result := make(map[string][]string)
if len(issueIDs) == 0 {
return result, nil
}
placeholders := make([]string, len(issueIDs))
args := make([]any, len(issueIDs))
for i, id := range issueIDs {
placeholders[i] = "?"View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error via errors.Unwrap/As to see the exact scan failure (unsupported Scan, converting NULL to string, etc.)
- Check the labels table schema: the label column should be NOT NULL and text-typed; migrate any NULL rows
- If NULLs are expected, alter the query to use COALESCE(label, '') or scan into a *string/sql.NullString
- Verify the driver in use matches the schema (e.g. re-run schema migrations for the embedded Dolt database)
Example fix
// before
var label string
if err := rows.Scan(&label); err != nil { ... }
// after
var label sql.NullString
if err := rows.Scan(&label); err != nil { ... }
if label.Valid { out = append(out, label.String) } Defensive patterns
Strategy: try-catch
Validate before calling
// before calling List, verify schema var notNull, dtype string err := rawRepo.QueryRow(ctx, `SELECT COUNT(*) FROM information_schema.columns WHERE table_name='issue_labels' AND column_name='label' AND is_nullable='NO'`).Scan(¬Null) // or check migrations ran before opening repos
Type guard
func isScanErr(err error) bool {
var s *fmt.ScanError // or check strings.Contains(err.Error(), "Scan")
return err != nil && strings.Contains(err.Error(), "unsupported Scan")
} Try / catch
labels, err := repo.List(ctx, opts)
if err != nil {
if strings.Contains(err.Error(), "scan: ") {
// inspect cause
log.Printf("label scan failed: %v", errors.Unwrap(err))
}
return err
} Prevention
- Keep label column NOT NULL in migrations
- Use COALESCE for nullable text columns
- Run schema migrations at startup before repository use
- Test repositories against the real driver, not only mocks
When it happens
Trigger: Calling List when a row value is not scannable into *string — e.g. a NULL in the label column, or a driver returning an unexpected type for the label column.
Common situations: Schema drift after a migration changed the label column to nullable or to a non-string type; a custom or mocked driver returning exotic types (e.g. []byte with non-UTF8 data handled unexpectedly); using an embedded/Dolt driver with different NULL handling.
Related errors
- db: ChildCounterSQLRepository.NextChildID: scan: %w
- db: CommentSQLRepository.CountsByIssueIDs: scan: %w
- db: CommentSQLRepository.ListByIssueIDs: scan: %w
- db: LabelSQLRepository.ListByIssueIDs: scan: %w
- get issues by IDs: scan: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ef7b9f9f5ae99fdf.
Report an issue: GitHub.