gastownhall/beads · error
db: DependencySQLRepository.CountsByIssueIDs (in): %w
Error message
db: DependencySQLRepository.CountsByIssueIDs (in): %w
What it means
Wraps a failure from the incoming 'blocks' count query in CountsByIssueIDs (COUNT(*) grouped by depends_on_id for the DependentCount field). The outgoing count succeeded but the inbound aggregate failed, so the whole counts map is discarded (returns nil, error).
Source
Thrown at internal/storage/domain/db/dependency.go:476
idPlaceholders, idArgs := buildInPlaceholders(issueIDs)
table := pickDepTable(opts.UseWispsTable)
//nolint:gosec // G201: table is one of two hardcoded constants
outQ := fmt.Sprintf(
`SELECT issue_id, COUNT(*) FROM %s WHERE issue_id IN (%s) AND type = 'blocks' GROUP BY issue_id`,
table, idPlaceholders,
)
if err := scanCounts(ctx, r.runner, outQ, idArgs, result, func(c *types.DependencyCounts, n int) { c.DependencyCount = n }); err != nil {
return nil, fmt.Errorf("db: DependencySQLRepository.CountsByIssueIDs (out): %w", err)
}
//nolint:gosec // G201: table and depTargetExpr are hardcoded
inQ := fmt.Sprintf(
`SELECT %s AS depends_on_id, COUNT(*) FROM %s WHERE %s IN (%s) AND type = 'blocks' GROUP BY %s`,
depTargetExpr, table, depTargetExpr, idPlaceholders, depTargetExpr,
)
if err := scanCounts(ctx, r.runner, inQ, idArgs, result, func(c *types.DependencyCounts, n int) { c.DependentCount = n }); err != nil {
return nil, fmt.Errorf("db: DependencySQLRepository.CountsByIssueIDs (in): %w", err)
}
return result, nil
}
func (r *dependencySQLRepositoryImpl) GetBlockingInfo(ctx context.Context, issueIDs []string, opts domain.DepListOpts) (domain.BlockingInfo, error) {
info := domain.BlockingInfo{
BlockedBy: make(map[string][]string),
Blocks: make(map[string][]string),
Parent: make(map[string]string),
}
if len(issueIDs) == 0 {
return info, nil
}
table := pickDepTable(opts.UseWispsTable)
idPlaceholders, idArgs := buildInPlaceholders(issueIDs)
View on GitHub (pinned to 71377f2769)
Solutions
- Retry the whole call; counts are cheap read-only aggregates and both halves must succeed for a consistent map.
- Chunk issueIDs to avoid placeholder limits.
- Verify UseWispsTable matches the deps table.
- Check connection stability/pool settings if only the second query keeps failing.
Example fix
// before
counts, err := deps.CountsByIssueIDs(ctx, ids, opts)
if err != nil { return nil, err } // may be the (in) half failing transiently
// after
counts, err := retry.Do(ctx, 3, backoff, func() (map[string]*types.DependencyCounts, error) {
return deps.CountsByIssueIDs(ctx, ids, opts)
}) Defensive patterns
Strategy: retry
Validate before calling
if len(issueIDs) == 0 { return map[string]*types.DependencyCounts{}, nil }
if len(issueIDs) > 500 { /* chunk before calling */ } Try / catch
counts, err := deps.CountsByIssueIDs(ctx, ids, opts)
if err != nil {
if isTransientDBError(err) {
counts, err = deps.CountsByIssueIDs(ctx, ids, opts) // retry whole call for consistency
}
} Prevention
- Retry the full call, not one half, so DependencyCount and DependentCount stay consistent.
- Chunk IDs to avoid placeholder limits.
- Keep connection pool healthy; mid-call drops trigger this on the second query.
- Verify the wisps-table flag before bulk counts.
When it happens
Trigger: CountsByIssueIDs(ctx, issueIDs, opts): the inbound aggregate SELECT fails or scanCounts errors — connection drop between the two queries, placeholder limit, wisps-table mismatch, or type-scan mismatch.
Common situations: Same bulk-count contexts as (out), plus transient mid-batch connection loss where the first query succeeds and the second fails.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- db: DependencySQLRepository.CountsByIssueIDs (out): %w
- ErrQuery
- failed to get federation peer: %w
- failed to list federation peers: %w
- failed to get comments: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/3222a3b904b9f378.
Report an issue: GitHub.