gastownhall/beads · error
count edges in %s: rows: %w
Error message
count edges in %s: rows: %w
What it means
After consuming all rows of the edge-count query, rows.Err() returned a non-nil error, meaning the result set was interrupted mid-iteration (connection loss, cancellation, driver I/O error) rather than ending normally. The table name is included to locate the failing plane.
Source
Thrown at internal/storage/issueops/edge_counts.go:164
rows, err := tx.QueryContext(ctx, query, edgeCountArgs(batch, request)...)
if err != nil {
if optionalBlockedTable(plane.dependencies) && isTableNotExistError(err) {
break
}
return nil, fmt.Errorf("count edges in %s: %w", plane.dependencies, err)
}
for rows.Next() {
var id string
var n int64
if scanErr := rows.Scan(&id, &n); scanErr != nil {
_ = rows.Close()
return nil, fmt.Errorf("count edges in %s: scan: %w", plane.dependencies, scanErr)
}
tallies[id] += n
}
_ = rows.Close()
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("count edges in %s: rows: %w", plane.dependencies, err)
}
}
}
return tallies, nil
}
// buildEdgeCountQuery returns the grouped count for one dependency plane, keyed
// by the anchor end the request's direction names.
//
// THE TARGET END IS ALWAYS THE COALESCE EXPRESSION, never the STORED generated
// `depends_on_id` column. Both dependency tables define that column as
// GENERATED ALWAYS AS the same COALESCE, and inside an aggregate the pure-Go
// GMS analyzer can prune the base columns it derives from and then fail with
// "column depends_on_id could not be found in any table in scope"
// (dolt/counts.go says so at depTargetExpr). Every other aggregate over these
// tables in this package resolves the target the same way.
func buildEdgeCountQuery(depTable, sourceTable string, batchSize int, request publicops.EdgeCountRequest) string {
placeholders := strings.TrimSuffix(strings.Repeat("?,", batchSize), ",")View on GitHub (pinned to 71377f2769)
Solutions
- Retry the count; the error is usually transient (connection/cancellation).
- Increase query/connection timeouts or batch size tuning so iteration completes within limits.
- Check context deadlines upstream and give the operation a longer budget.
- Inspect the wrapped error (rows.Err chain) for driver-specific codes like bad connection and enable driver auto-reconnect where appropriate.
Defensive patterns
Strategy: retry
Try / catch
res, err := ExecuteEdgeCount(ctx, tx, req)
if err != nil && strings.Contains(err.Error(), ": rows: ") {
// typically transient: retry with backoff and a fresh transaction
res, err = retryWithBackoff(func() (publicops.EdgeCountResult, error) { return ExecuteEdgeCount(ctx, tx, req) })
} Prevention
- Give large counts a generous context deadline
- Retry with backoff on rows-iteration errors
- Avoid proxies/idle timeouts shorter than the query duration
- Reopen the transaction on retry rather than reusing a possibly dead tx
When it happens
Trigger: Network drop or server restart while streaming rows of a large edge-count batch; ctx cancellation during iteration; driver-level read timeouts on big result sets.
Common situations: Counting edges for thousands of anchors where iteration outlasts the connection lifetime; a proxy/firewall idle timeout killing the connection; context deadlines in CLI commands cancelled by the user or a supervisor.
Related errors
- iterate dependency sources: %w
- iterate dependency targets: %w
- search %s (hydrate): rows: %w
- db: ChildCounterSQLRepository.NextChildID: rows: %w
- db: CommentSQLRepository.CountsByIssueIDs: rows: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0b6d664285528226.
Report an issue: GitHub.