gastownhall/beads · error
db: LabelSQLRepository.List %s: %w
Error message
db: LabelSQLRepository.List %s: %w
What it means
Wraps failure of the SELECT label query in LabelSQLRepository.List, adding the issue ID. Thrown when the driver rejects the query (connection loss, missing table, permissions), preventing retrieval of an issue's labels.
Source
Thrown at internal/storage/domain/db/label.go:135
OldValue: label,
}, domain.RecordEventOpts{UseWispsTable: opts.UseWispsTable}); err != nil {
return err
}
return issueops.RecordEventInTx(ctx, r.runner, issueops.EventUpdate, issueID, actor)
}
func (r *labelSQLRepositoryImpl) List(ctx context.Context, issueID string, opts domain.LabelOpts) ([]string, error) {
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) {View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped driver error, especially context.DeadlineExceeded
- Verify the labels table exists in this database
- Check DB connectivity and pool configuration
- Confirm UseWispsTable matches your storage mode
Example fix
// before
ctx := context.Background()
labels, err := repo.List(ctx, issueID, opts)
// after
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
labels, err := repo.List(ctx, issueID, opts)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) { /* retry */ }
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
if issueID == "" { return fmt.Errorf("issueID required") }
ctx, cancel := context.WithTimeout(ctx, 5*time.Second); defer cancel() Type guard
func isTimeout(err error) bool { return errors.Is(err, context.DeadlineExceeded) } Try / catch
labels, err := repo.List(ctx, issueID, opts)
if err != nil {
var sqle *mysql.MySQLError
switch {
case errors.Is(err, context.DeadlineExceeded):
return retry(ctx, issueID, opts)
case errors.As(err, &sqle) && sqle.Number == 1146:
return nil, fmt.Errorf("labels table missing; run migrations")
}
return nil, err
} Prevention
- Use context timeouts on repository reads
- Run migrations so the labels tables exist
- Confirm UseWispsTable matches the storage mode
- Retry read queries on transient failures
When it happens
Trigger: List called when the DB is unreachable, the labels table does not exist, or the query is cancelled via ctx (deadline/context cancellation).
Common situations: Context timeout cancelling a slow query; database not migrated so the labels table is absent; connection pool exhausted; wrong UseWispsTable mode for the current database.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- failed to get federation peer: %w
- failed to list federation peers: %w
- iter dependents: query: %w
- db: ChildCounterSQLRepository.NextChildID: scan existing chi
- db: CommentSQLRepository.CountsByIssueIDs: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f43e54bd761e7f16.
Report an issue: GitHub.