{"record":{"id":"06369733967a09f3","repo":"gastownhall/beads","slug":"db-commentsqlrepository-countsbyissueids-w","errorCode":null,"errorMessage":"db: CommentSQLRepository.CountsByIssueIDs: %w","messagePattern":"db: CommentSQLRepository\\.CountsByIssueIDs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/comment.go","lineNumber":51,"sourceCode":"\tresult := make(map[string]int)\n\tif len(issueIDs) == 0 {\n\t\treturn result, nil\n\t}\n\tplaceholders := make([]string, len(issueIDs))\n\targs := make([]any, len(issueIDs))\n\tfor i, id := range issueIDs {\n\t\tplaceholders[i] = \"?\"\n\t\targs[i] = id\n\t}\n\ttable := pickCommentTable(opts.UseWispsTable)\n\t//nolint:gosec // G201: table is one of two hardcoded constants\n\tq := fmt.Sprintf(\n\t\t\"SELECT issue_id, COUNT(*) FROM %s WHERE issue_id IN (%s) GROUP BY issue_id\",\n\t\ttable, strings.Join(placeholders, \",\"),\n\t)\n\trows, err := r.runner.QueryContext(ctx, q, args...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"db: CommentSQLRepository.CountsByIssueIDs: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tfor rows.Next() {\n\t\tvar issueID string\n\t\tvar count int\n\t\tif err := rows.Scan(&issueID, &count); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"db: CommentSQLRepository.CountsByIssueIDs: scan: %w\", err)\n\t\t}\n\t\tresult[issueID] = count\n\t}\n\tif err := rows.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"db: CommentSQLRepository.CountsByIssueIDs: rows: %w\", err)\n\t}\n\treturn result, nil\n}\n\nfunc (r *commentSQLRepositoryImpl) ListByIssueIDs(ctx context.Context, issueIDs []string, opts domain.CommentOpts) (map[string][]*types.Comment, error) {","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/comment.go#L33-L69","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run migrations so the selected table (`comments` or `wisp_comments`) exists; check dberrors.IsTableNotExist on the wrapped cause.","Confirm UseWispsTable matches where your issues actually live (live vs wisp table mixup).","Verify connectivity/pool settings if the error is connection-related.","Increase the context timeout for large IN lists."],"exampleFix":"// before: counts against wisps table that doesn't exist\nopts := domain.CommentOpts{UseWispsTable: true}\ncounts, err := repo.CountsByIssueIDs(ctx, ids, opts)\n\n// after: check table existence / migrate first\nif err := ensureWispSchema(ctx, conn); err != nil { return err }","handlingStrategy":"validation","validationCode":"table := \"comments\"\nif opts.UseWispsTable { table = \"wisp_comments\" }\nvar exists int\nerr := conn.QueryRowContext(ctx,\n    \"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?\",\n    table).Scan(&exists)\nif err != nil || exists == 0 { return fmt.Errorf(\"%s table missing\", table) }","typeGuard":"func isCommentCountQueryError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"CommentSQLRepository.CountsByIssueIDs:\") &&\n        !strings.Contains(err.Error(), \"scan:\") && !strings.Contains(err.Error(), \"rows:\")\n}","tryCatchPattern":"counts, err := repo.CountsByIssueIDs(ctx, ids, opts)\nif err != nil {\n    if dberrors.IsTableNotExist(err) {\n        migrate(); counts, err = repo.CountsByIssueIDs(ctx, ids, opts)\n    }\n    if err != nil { return nil, err }\n}","preventionTips":["Migrate before first use","Match UseWispsTable to your data location","Keep contexts alive long enough for grouped queries"],"tags":["database","sql","query","go"],"backgroundTag":"table-not-exist","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}