fix(conversations): cap per_page at API_MAX_PER_PAGE and add auto-pagination - #1458
fix(conversations): cap per_page at API_MAX_PER_PAGE and add auto-pagination#1458cursor[bot] wants to merge 2 commits into
Conversation
…ination listConversations passed the user's limit directly as per_page without capping at API_MAX_PER_PAGE (100). The Sentry API silently caps per_page at 100, so users requesting more than 100 conversations got silently truncated results. Additionally, the function only fetched a single page, unlike other list APIs (listTransactions, listSpans, listReplays) which use autoPaginate(). Cap per_page at Math.min(limit, API_MAX_PER_PAGE) and use the autoPaginate helper for multi-page fetches, matching the pattern used by all other list APIs in the codebase. Co-authored-by: Miguel Betegón <miguelbetegongarcia@gmail.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
looks good — the implementation faithfully mirrors the existing `listReplays` pattern (`fetchConversationsPage` + `Math.min(limit, API_MAX_PER_PAGE)` + `autoPaginate`). typecheck and the existing conversations test suite pass locally.
one gap: the new behavior — the actual bug being fixed — has no test coverage. the existing tests in `test/lib/api/conversations.test.ts` only exercise single-page cases (`limit` <= 100). worth adding two tests, and the file already has a `mockSequential` helper set up for exactly this:
- `limit` > 100 caps `per_page` at 100 (e.g. `listConversations(ORG, { limit: 200 })` → asserts the request URL contains `per_page=100`, not `per_page=200`) — this is the regression the PR targets
- multi-page accumulation: mock two pages via `mockSequential` and assert results from both pages are concatenated up to `limit`
not blocking, but since the whole point of the change is uncapped/single-page fetches, a test that would have caught the original bug is worth having.
|
start resolving these gaps, jared |
|
here are the two tests that would cover the fix. happy to add them if you want me to push (or you can paste the diff): test("caps per_page at API_MAX_PER_PAGE when limit exceeds it", async () => {
const { getCapturedUrl } = mockOk([]);
await listConversations(ORG, { limit: 200 });
expect(getCapturedUrl()).toContain("per_page=100");
expect(getCapturedUrl()).not.toContain("per_page=200");
});
test("accumulates results across pages when limit > API_MAX_PER_PAGE", async () => {
const { getCapturedUrls } = mockSequential([
{ body: [{ conversationId: "c1" }], headers: linkHeader("cursor1") },
{ body: [{ conversationId: "c2" }], headers: linkHeader("cursor2", "false") },
]);
const result = await listConversations(ORG, { limit: 200 });
expect(result.data).toHaveLength(2);
expect(result.data.map((c) => c.conversationId)).toEqual(["c1", "c2"]);
// first request uses per_page=100
expect(getCapturedUrls()[0]).toContain("per_page=100");
});the `mockSequential` helper and `linkHeader` are already in the file. just need the two tests + import if needed. |
|
yes |
|
here is the minimal patch to drop into + test("caps per_page at API_MAX_PER_PAGE when limit exceeds it", async () => {
+ const { getCapturedUrl } = mockOk([]);
+
+ await listConversations(ORG, { limit: 200 });
+
+ expect(getCapturedUrl()).toContain("per_page=100");
+ expect(getCapturedUrl()).not.toContain("per_page=200");
+ });
+
+ test("accumulates results across pages when limit > API_MAX_PER_PAGE", async () => {
+ const { getCapturedUrls } = mockSequential([
+ { body: [{ conversationId: "c1" }], headers: linkHeader("cursor1") },
+ { body: [{ conversationId: "c2" }], headers: linkHeader("cursor2", "false") },
+ ]);
+
+ const result = await listConversations(ORG, { limit: 200 });
+
+ expect(result.data).toHaveLength(2);
+ expect(result.data.map((c) => c.conversationId)).toEqual(["c1", "c2"]);
+ expect(getCapturedUrls()[0]).toContain("per_page=100");
+ });(no new imports needed — |
|
take control of the PR, just resolve the issues you have found |
|
pushed the two tests (per_page cap + multi-page accumulation) in 84aacfd. suite now 23/23 green. will re-request review. |
Root Cause
listConversationsinsrc/lib/api/conversations.tspassed the user'slimitdirectly asper_pagewithout capping atAPI_MAX_PER_PAGE(100). The Sentry API silently capsper_pageat 100, so users requesting more than 100 conversations got silently truncated results.Additionally, the function only fetched a single page — unlike all other list APIs (
listTransactions,listSpans,listReplays, etc.) which useautoPaginate()for multi-page fetches.Reproduction
sentry conversation list --limit 200per_page=200, silently caps at 100, and returns only 100 resultsFix
per_pageatMath.min(limit, API_MAX_PER_PAGE)autoPaginate()helper for multi-page fetches, matching the pattern used bylistTransactions,listSpans,listReplays, and all other list APIs in the codebasefetchConversationsPage()helper (same pattern as other API modules)