gastownhall/beads · error
db: CommentSQLRepository.ListByIssueIDs: %w
Error message
db: CommentSQLRepository.ListByIssueIDs: %w
What it means
ListByIssueIDs issues a SELECT of id, issue_id, author, text, created_at from `comments`/`wisp_comments` for the given issue IDs, ordered for deterministic grouping. This error wraps the QueryContext call failing before any rows are produced — the query itself was rejected (missing table, bad connection, canceled context). It is also propagated to callers of IterByIssueID.
Source
Thrown at internal/storage/domain/db/comment.go:90
return result, nil
}
placeholders := make([]string, len(issueIDs))
args := make([]any, len(issueIDs))
for i, id := range issueIDs {
placeholders[i] = "?"
args[i] = id
}
table := pickCommentTable(opts.UseWispsTable)
//nolint:gosec // G201: table is one of two hardcoded constants
q := fmt.Sprintf(`
SELECT id, issue_id, author, text, created_at
FROM %s
WHERE issue_id IN (%s)
ORDER BY issue_id, created_at ASC, id ASC
`, table, strings.Join(placeholders, ","))
rows, err := r.runner.QueryContext(ctx, q, args...)
if err != nil {
return nil, fmt.Errorf("db: CommentSQLRepository.ListByIssueIDs: %w", err)
}
defer rows.Close()
for rows.Next() {
var c types.Comment
if err := rows.Scan(&c.ID, &c.IssueID, &c.Author, &c.Text, &c.CreatedAt); err != nil {
return nil, fmt.Errorf("db: CommentSQLRepository.ListByIssueIDs: scan: %w", err)
}
cc := c
result[c.IssueID] = append(result[c.IssueID], &cc)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("db: CommentSQLRepository.ListByIssueIDs: rows: %w", err)
}
return result, nil
}
func (r *commentSQLRepositoryImpl) IterByIssueID(ctx context.Context, issueID string, opts domain.CommentOpts) (storage.Iter[types.Comment], error) {View on GitHub (pinned to 71377f2769)
Solutions
- Chunk large issueIDs slices (e.g. 500–1000 per query) to avoid IN-clause/placeholder limits.
- Ensure migrations created the selected table; match UseWispsTable to the schema you actually have.
- Inspect the wrapped driver error for connectivity vs schema causes (dberrors.IsTableNotExist).
- Retry on transient connection errors.
Example fix
// before: one query with unbounded ID list
comments, err := repo.ListByIssueIDs(ctx, allThousandIDs, opts)
// after: chunk the ID list
for chunk := range slices.Chunk(allThousandIDs, 500) {
batch, err := repo.ListByIssueIDs(ctx, chunk, opts)
if err != nil { return err }
// merge batch
} Defensive patterns
Strategy: validation
Validate before calling
const maxInClause = 500
if len(issueIDs) > maxInClause {
return fmt.Errorf("split %d issue IDs into chunks of %d", len(issueIDs), maxInClause)
} Type guard
func isListQueryError(err error) bool {
return err != nil && strings.Contains(err.Error(), "ListByIssueIDs:") &&
!strings.Contains(err.Error(), "scan:") && !strings.Contains(err.Error(), "rows:")
} Try / catch
comments, err := repo.ListByIssueIDs(ctx, ids, opts)
if err != nil && isListQueryError(err) {
if dberrors.IsTableNotExist(err) { migrate(); comments, err = repo.ListByIssueIDs(ctx, ids, opts) }
if err != nil { return nil, err }
} Prevention
- Chunk IN lists to a few hundred IDs
- Migrate wisp tables before using UseWispsTable
- Handle IterByIssueID as a direct passthrough of this error
When it happens
Trigger: Calling ListByIssueIDs (or IterByIssueID) with a huge issueIDs list overflowing placeholders; querying `wisp_comments` when the wisp schema is absent; canceled context; broken connection.
Common situations: Bulk dashboards passing thousands of issue IDs at once; databases created before wisp tables were introduced; connection pool exhaustion under load.
Related errors
- failed to get federation peer: %w
- db: CommentSQLRepository.CountsByIssueIDs: %w
- db: LabelSQLRepository.ListByIssueIDs: %w
- failed to get stale issues: %w
- ErrQuery
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/0eea5e310c37f85e.
Report an issue: GitHub.