gastownhall/beads · error

db: CommentSQLRepository.CountsByIssueIDs: %w

Error message

db: CommentSQLRepository.CountsByIssueIDs: %w

What it means

CountsByIssueIDs runs a grouped COUNT query over `comments`/`wisp_comments` filtered by an IN list of issue IDs. This error wraps a QueryContext failure — the query never produced rows. It indicates the comment table is missing or the query was rejected/canceled before execution completed.

Source

Thrown at internal/storage/domain/db/comment.go:51

	result := make(map[string]int)
	if len(issueIDs) == 0 {
		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 issue_id, COUNT(*) FROM %s WHERE issue_id IN (%s) GROUP BY issue_id",
		table, strings.Join(placeholders, ","),
	)
	rows, err := r.runner.QueryContext(ctx, q, args...)
	if err != nil {
		return nil, fmt.Errorf("db: CommentSQLRepository.CountsByIssueIDs: %w", err)
	}
	defer rows.Close()

	for rows.Next() {
		var issueID string
		var count int
		if err := rows.Scan(&issueID, &count); err != nil {
			return nil, fmt.Errorf("db: CommentSQLRepository.CountsByIssueIDs: scan: %w", err)
		}
		result[issueID] = count
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("db: CommentSQLRepository.CountsByIssueIDs: rows: %w", err)
	}
	return result, nil
}

func (r *commentSQLRepositoryImpl) ListByIssueIDs(ctx context.Context, issueIDs []string, opts domain.CommentOpts) (map[string][]*types.Comment, error) {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run migrations so the selected table (`comments` or `wisp_comments`) exists; check dberrors.IsTableNotExist on the wrapped cause.
  2. Confirm UseWispsTable matches where your issues actually live (live vs wisp table mixup).
  3. Verify connectivity/pool settings if the error is connection-related.
  4. Increase the context timeout for large IN lists.

Example fix

// before: counts against wisps table that doesn't exist
opts := domain.CommentOpts{UseWispsTable: true}
counts, err := repo.CountsByIssueIDs(ctx, ids, opts)

// after: check table existence / migrate first
if err := ensureWispSchema(ctx, conn); err != nil { return err }
Defensive patterns

Strategy: validation

Validate before calling

table := "comments"
if opts.UseWispsTable { table = "wisp_comments" }
var exists int
err := conn.QueryRowContext(ctx,
    "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?",
    table).Scan(&exists)
if err != nil || exists == 0 { return fmt.Errorf("%s table missing", table) }

Type guard

func isCommentCountQueryError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "CommentSQLRepository.CountsByIssueIDs:") &&
        !strings.Contains(err.Error(), "scan:") && !strings.Contains(err.Error(), "rows:")
}

Try / catch

counts, err := repo.CountsByIssueIDs(ctx, ids, opts)
if err != nil {
    if dberrors.IsTableNotExist(err) {
        migrate(); counts, err = repo.CountsByIssueIDs(ctx, ids, opts)
    }
    if err != nil { return nil, err }
}

Prevention

When it happens

Trigger: Calling CountsByIssueIDs with opts.UseWispsTable=true when `wisp_comments` doesn't exist; the table name resolves via pickCommentTable and a missing table yields a driver error; canceled context; malformed connection state.

Common situations: Querying wisps tables on a database where the wisp schema hasn't been migrated; connection pool exhausted or server unreachable; context deadline exceeded on slow servers.

Related errors


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