From 6513c9e5faea4a04f7f351624162d61a0733dddd Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2026 12:24:29 +0000 Subject: [PATCH] fix(cli): Flatten release list results for session-based sorts The releases endpoint rejects the sessions, users, and crash-free sorts with a 400 unless flatten=1 is set, so release list --sort sessions/users/cfs/cfu always failed. Send flatten=1 for those sorts. --- packages/cli/src/lib/api/releases.ts | 13 ++++++ packages/cli/test/lib/api/releases.test.ts | 46 ++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/packages/cli/src/lib/api/releases.ts b/packages/cli/src/lib/api/releases.ts index 73db501b8..dc3eb7633 100644 --- a/packages/cli/src/lib/api/releases.ts +++ b/packages/cli/src/lib/api/releases.ts @@ -61,6 +61,17 @@ export type ListReleasesOptions = { status?: string; }; +/** + * Sorts the releases endpoint only accepts with `flatten=1`; otherwise it + * responds 400 "sorting by crash statistics requires flattening". + */ +const SESSION_SORTS = new Set([ + "sessions", + "users", + "crash_free_sessions", + "crash_free_users", +]); + export async function listReleasesPaginated( orgSlug: string, options: ListReleasesOptions = {}, @@ -76,6 +87,7 @@ export async function listReleasesPaginated( per_page: options.perPage ?? 25, query: options.query, sort: options.sort, + flatten: options.sort && SESSION_SORTS.has(options.sort) ? 1 : undefined, health: options.health ? 1 : undefined, project: options.project, environment: options.environment, @@ -86,6 +98,7 @@ export async function listReleasesPaginated( per_page?: number; query?: string; sort?: string; + flatten?: number; health?: number; project?: number[]; environment?: string[]; diff --git a/packages/cli/test/lib/api/releases.test.ts b/packages/cli/test/lib/api/releases.test.ts index 4d7218442..2eb2ba8c5 100644 --- a/packages/cli/test/lib/api/releases.test.ts +++ b/packages/cli/test/lib/api/releases.test.ts @@ -614,4 +614,50 @@ describe("listReleasesPaginated", () => { expect(result.data).toHaveLength(0); }); + + test.each(["sessions", "users", "crash_free_sessions", "crash_free_users"])( + "requests flattened results when sorting by %s", + async (sort) => { + let flatten: string | null = null; + globalThis.fetch = mockFetch(async (input, init) => { + const url = new URL(new Request(input!, init).url); + flatten = url.searchParams.get("flatten"); + // Sentry rejects session sorts unless the results are flattened. + if (flatten !== "1") { + return new Response( + JSON.stringify({ + detail: + "sorting by crash statistics requires flattening (flatten=1)", + }), + { status: 400, headers: { "Content-Type": "application/json" } }, + ); + } + return new Response(JSON.stringify([SAMPLE_RELEASE]), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); + }); + + const result = await listReleasesPaginated("test-org", { sort }); + + expect(flatten).toBe("1"); + expect(result.data).toHaveLength(1); + }, + ); + + test("does not flatten date-sorted results", async () => { + let flatten: string | null = "unset"; + globalThis.fetch = mockFetch(async (input, init) => { + const url = new URL(new Request(input!, init).url); + flatten = url.searchParams.get("flatten"); + return new Response(JSON.stringify([]), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); + }); + + await listReleasesPaginated("test-org", { sort: "date" }); + + expect(flatten).toBeNull(); + }); });