gastownhall/beads · error
count edges in %s: scan: %w
Error message
count edges in %s: scan: %w
What it means
tallyEdgesInTx failed while scanning a row of the grouped edge-count result into (id string, count int64). rows.Scan returned an error because the returned columns did not match the expected string/int64 shapes. The rows are closed before returning so the connection is not leaked.
Source
Thrown at internal/storage/issueops/edge_counts.go:158
end := start + queryBatchSize
if end > len(anchors) {
end = len(anchors)
}
batch := anchors[start:end]
query := buildEdgeCountQuery(plane.dependencies, plane.sources, len(batch), request)
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-GoView on GitHub (pinned to 71377f2769)
Solutions
- Check the driver's type mapping for COUNT/aggregate results (e.g. uint64 vs int64) and pin a supported driver version.
- Make the query's COALESCE/COUNT output non-NULL and compatible (CAST if needed).
- Inspect the wrapped scan error message — it names the offending column and Go type.
- If the code was customized, re-align rows.Scan with buildEdgeCountQuery's SELECT list.
Example fix
// before
var n int64
if scanErr := rows.Scan(&id, &n); scanErr != nil { ... }
// after
var n any // or uint64, matching the driver
count, ok := n.(uint64)
if ok { n = int64(count) } Defensive patterns
Strategy: try-catch
Try / catch
res, err := ExecuteEdgeCount(ctx, tx, req)
if err != nil && strings.Contains(err.Error(), ": scan: ") {
log.Errorf("edge count scan failure: %v", err) // inspect driver type mapping
} Prevention
- Pin a supported Dolt/MySQL driver version
- Keep id columns NOT NULL
- Do not customize buildEdgeCountQuery's SELECT list without updating the scan
- Test counts against your actual driver, not just the default
When it happens
Trigger: A driver returning columns whose Go types cannot convert to string/int64 (e.g. NULL id, a count column typed as unsigned bigint beyond int64, or a decimal count from a custom COUNT expression); a driver mismatch producing different column types than Dolt normally does.
Common situations: Using a non-Dolt/MySQL driver or a driver version whose type mapping changed; a schema where the id column is nullable and a NULL row appears; a modified buildEdgeCountQuery selecting an extra/different column while the scan still expects two.
Related errors
- check issue existence in %s: scan: %w
- %s: %w
- failed to scan federation peer: %w
- db: ChildCounterSQLRepository.NextChildID: scan: %w
- db: CommentSQLRepository.CountsByIssueIDs: scan: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/7bf7ed0e8654e663.
Report an issue: GitHub.