gastownhall/beads · error

iter issues: rows: %w

Error message

iter issues: rows: %w

What it means

After scanning all rows, IterIssues calls rows.Err() to detect deferred iteration errors from the driver (connection loss, context cancellation mid-scan). If the result stream itself failed, the whole materialization is abandoned and this wrapped error is returned.

Source

Thrown at internal/storage/dolt/iter_issues.go:77

	var issues []*types.Issue
	txErr := s.withReadTx(ctx, func(tx *sql.Tx) error {
		rows, err := tx.QueryContext(ctx, q, args...)
		if err != nil {
			return fmt.Errorf("iter issues: query: %w", err)
		}
		defer func() { _ = rows.Close() }()
		ids := make([]string, 0)
		for rows.Next() {
			iss, scanErr := issueops.ScanIssueFrom(rows)
			if scanErr != nil {
				return fmt.Errorf("iter issues: scan: %w", scanErr)
			}
			issues = append(issues, iss)
			ids = append(ids, iss.ID)
		}
		if err := rows.Err(); err != nil {
			return fmt.Errorf("iter issues: rows: %w", err)
		}
		// A *sql.Tx is bound to one connection, so the cursor must be closed
		// before the label query can run on it (idempotent with the defer).
		_ = rows.Close()
		labelMap, err := issueops.GetLabelsForIssuesFromTableInTx(ctx, tx, "labels", ids)
		if err != nil {
			return fmt.Errorf("iter issues: hydrate labels: %w", err)
		}
		for _, iss := range issues {
			if labels, ok := labelMap[iss.ID]; ok {
				iss.Labels = labels
			}
		}
		return nil
	})
	if txErr != nil {
		return nil, txErr
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Increase the context timeout or remove early cancellation for large iterations
  2. Retry the call — transient connection drops are often recoverable
  3. Check Dolt server health/logs for the underlying transport error
  4. Paginate via filters/limits if result sets are very large

Example fix

// before
tissues, err := store.IterIssues(ctx, "", types.IssueFilter{})

// after: generous timeout for large exports
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
tissues, err := store.IterIssues(ctx, "", types.IssueFilter{})
Defensive patterns

Strategy: retry

Try / catch

var iter storage.Iter[types.Issue]
err := retryWithBackoff(3, func() error {
    var e error
    iter, e = store.IterIssues(ctx, query, filter)
    return e
})
if err != nil { return err }

Prevention

When it happens

Trigger: Calling IterIssues when the connection drops or the context is cancelled while rows are being streamed inside withReadTx, so the scan loop completed but the driver reports an error at rows.Err().

Common situations: Slow/large queries hitting context deadline; Dolt server restart or network drop mid-query; connection pool exhaustion causing the tx connection to be reclaimed.

Related errors


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