gastownhall/beads · error
iterate wisp issues by label: %w
Error message
iterate wisp issues by label: %w
What it means
GetIssuesByLabelInTx wraps a row-iteration error from the wisp-issues label query with this message after rows.Scan succeeded but wispRows.Err() reported a driver/SQL failure mid-iteration. It means the ID list is incomplete because the underlying query failed while advancing the result set.
Source
Thrown at internal/storage/issueops/bulk_ops.go:86
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate issues by label: %w", err)
}
wispRows, err := tx.QueryContext(ctx, `SELECT issue_id FROM wisp_labels WHERE label = ?`, label)
if err != nil {
return nil, fmt.Errorf("get wisp issues by label: %w", err)
}
defer wispRows.Close()
for wispRows.Next() {
var id string
if err := wispRows.Scan(&id); err != nil {
return nil, fmt.Errorf("scan wisp issue id: %w", err)
}
ids = append(ids, id)
}
if err := wispRows.Err(); err != nil {
return nil, fmt.Errorf("iterate wisp issues by label: %w", err)
}
return ids, nil
}
// DeleteConfigInTx removes a configuration value.
func DeleteConfigInTx(ctx context.Context, tx *sql.Tx, key string) error {
_, err := tx.ExecContext(ctx, "DELETE FROM config WHERE `key` = ?", key)
if err != nil {
return fmt.Errorf("delete config %s: %w", key, err)
}
return nil
}
// GetCommentsForIssuesInTx retrieves comments for multiple issues, partitioning
// between comments and wisp_comments tables.
//
//nolint:gosec // G201: table is hardcodedView on GitHub (pinned to 71377f2769)
Solutions
- Retry GetIssuesByLabelInTx (the read is idempotent) once the connection/context is healthy.
- Inspect the wrapped driver error for connection/cancellation causes; extend the context deadline if it timed out.
- Check database server health/logs and connectivity before rerunning.
Example fix
// before
ids, err := issueops.GetIssuesByLabelInTx(ctx, tx, label) // err: iterate wisp issues by label: context deadline exceeded
// after
ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
defer cancel()
ids, err := issueops.GetIssuesByLabelInTx(ctx, tx, label)
if err != nil {
return retryRead(ctx, label) // bounded retry
} Defensive patterns
Strategy: retry
Type guard
func isIterationFailure(err error) bool { return err != nil && strings.Contains(err.Error(), "iterate wisp issues by label") } Try / catch
ids, err := issueops.GetIssuesByLabelInTx(ctx, tx, label)
if err != nil {
if ctx.Err() != nil || isTransientDB(err) {
return retryWithBackoff(3, func() error { _, e := issueops.GetIssuesByLabelInTx(ctx, tx, label); return e })
}
return err
} Prevention
- Use a context deadline generous enough for large label scans.
- Retry read-only queries on transient driver/connection errors.
- Monitor database server health for embedded/remote Dolt instances.
- Treat the returned ID list as incomplete after this error — always re-query.
When it happens
Trigger: The rows cursor over wisp issues by label hits a database error between Scan calls — connection drop, context cancellation/timeouts, Dolt server restart, or driver-level failure during iteration.
Common situations: Long-running bulk operations on flaky connections; CLI context timeout expiring mid-query; embedded Dolt process killed during a large label scan; network interruption in remote/server mode.
Related errors
- ErrQuery
- failed to get federation peer: %w
- db: CommentSQLRepository.CountsByIssueIDs: %w
- db: CommentSQLRepository.ListByIssueIDs: %w
- db: LabelSQLRepository.List: rows: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/981588441ca038d0.
Report an issue: GitHub.