gastownhall/beads · error
db: LabelSQLRepository.ListByIssueIDs: rows: %w
Error message
db: LabelSQLRepository.ListByIssueIDs: rows: %w
What it means
LabelSQLRepository.ListByIssueIDs failed after row iteration: rows.Err() reported an error that occurred while fetching rows. The result map is unreliable because streaming was interrupted.
Source
Thrown at internal/storage/domain/db/label.go:184
q := fmt.Sprintf(
"SELECT issue_id, label FROM %s WHERE issue_id IN (%s) ORDER BY issue_id, label",
table, strings.Join(placeholders, ","),
)
rows, err := r.runner.QueryContext(ctx, q, args...)
if err != nil {
return nil, fmt.Errorf("db: LabelSQLRepository.ListByIssueIDs: %w", err)
}
defer rows.Close()
for rows.Next() {
var issueID, label string
if err := rows.Scan(&issueID, &label); err != nil {
return nil, fmt.Errorf("db: LabelSQLRepository.ListByIssueIDs: scan: %w", err)
}
result[issueID] = append(result[issueID], label)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("db: LabelSQLRepository.ListByIssueIDs: rows: %w", err)
}
return result, nil
}
func (r *labelSQLRepositoryImpl) DeleteAllForIDs(ctx context.Context, ids []string, opts domain.LabelOpts) (int, error) {
if len(ids) == 0 {
return 0, nil
}
table := "labels"
if opts.UseWispsTable {
table = "wisp_labels"
}
total := 0
for start := 0; start < len(ids); start += deleteBatchSize {
end := start + deleteBatchSize
if end > len(ids) {
end = len(ids)
}View on GitHub (pinned to 71377f2769)
Solutions
- Unwrap the error for the driver-level cause (context deadline exceeded, connection reset)
- Extend caller context timeout or reduce the returned row count by batching issueIDs
- Check database server health/logs for aborted connections
- Retry the call with a fresh context if the failure was transient
Example fix
// before ctx := ctx // long-running, possibly expired m, err := repo.ListByIssueIDs(ctx, ids, opts) // after qctx, cancel := context.WithTimeout(ctx, 15*time.Second) defer cancel() m, err := repo.ListByIssueIDs(qctx, ids, opts)
Defensive patterns
Strategy: retry
Validate before calling
if len(issueIDs) == 0 { return map[string][]string{}, nil }
if _, ok := ctx.Deadline(); !ok {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, 15*time.Second)
defer cancel()
} Try / catch
var m map[string][]string
err := retry.Do(3, backoff, func() error {
var e error
m, e = repo.ListByIssueIDs(ctx, ids, opts)
return e
}) Prevention
- Retry transient iteration errors with backoff
- Bound result set size via batching of issueIDs
- Keep context deadlines proportional to expected row counts
- Verify network stability for remote databases
When it happens
Trigger: Calling ListByIssueIDs when the connection drops, the context is cancelled, or the driver errors while fetching the IN-clause result set.
Common situations: Context deadlines on broad IN queries returning many rows; network issues to a remote database; server-side interruption; embedded database being closed concurrently.
Related errors
- db: LabelSQLRepository.List: rows: %w
- failed to begin transaction: %w
- failed to recompute is_blocked: %w
- failed to commit is_blocked repairs: %w
- failed to query orphaned dependencies: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/73aea8b6e32a425d.
Report an issue: GitHub.