Dashboardsentry-api-schemaSession 02NPf5EJoTz0

Session 02NPf5EJoTz0

Full ID: 02NPf5EJoTz0FDo54
Messages: 10
Distillations: 0
Time range: 2026-08-06 13:29:52 — 2026-08-06 13:37:04

Conversation (10 messages)

Review the uncommitted implementation for issue #83 in /home/byk/Code/getsentry/sentry-api-schema. Focus on correctness, TypeScript soundness, generated wrapper API behavior, transport failures, documented vs undocumented status narrowing, build portability, and missing tests. Do not edit files. Inspect the working diff and generated src/error-results.gen.ts as needed. Return findings ordered by severity with exact file/line references; explicitly say if no findings.

gateway · 2026-08-06 13:29:52
result
No files found
result
No files found
result
/home/byk/Code/getsentry/sentry-api-schema/src/browser.ts
/home/byk/Code/getsentry/sentry-api-schema/src/zod.ts
/home/byk/Code/getsentry/sentry-api-schema/src/error-results.gen.ts
/home/byk/Code/getsentry/sentry-api-schema/src/pagination.gen.ts
/home/byk/Code/getsentry/sentry-api-schema/src/browser-client.ts
/home/byk/Code/getsentry/sentry-api-schema/src/sentry-errors.ts
/home/byk/Code/getsentry/sentry-api-schema/src/sentry-pagination.ts
/home/byk/Code/getsentry/sentry-api-schema/src/zod.gen.ts
/home/byk/Code/getsentry/sentry-api-schema/src/sdk.gen.ts
/home/byk/Code/getsentry/sentry-api-schema/src/client.gen.ts
/home/byk/Code/getsentry/sentry-api-schema/src/index.ts
/home/byk/Code/getsentry/sentry-api-schema/src/types.gen.ts
/home/byk/Code/getsentry/sentry-api-schema/src/client/utils.gen.ts
/home/byk/Code/getsentry/sentry-api-schema/src/client/types.gen.ts
/home/byk/Code/getsentry/sentry-api-schema/src/client/client.gen.ts
/home/byk/Code/getsentry/sentry-api-schema/src/client/index.ts
...
gateway · 2026-08-06 13:31:20
result
 M README.md
 M build.mjs
 M lib/sentry-pagination.ts
 M test/smoke.test.ts
 M test/typecheck.ts
?? lib/sentry-errors.ts
?? scripts/generate-error-results.mjs
 README.md                |  32 +++++++++++++
 build.mjs                |   9 +++-
 lib/sentry-pagination.ts | 117 +++++------------------------------------------
 test/smoke.test.ts       |  65 ++++++++++++++++++--------
 test/typecheck.ts        |  47 +++++++++++++------
 5 files changed, 130 insertions(+), 140 deletions(-)
diff --git a/README.md b/README.md
index f0701b7..898dd47 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,38 @@ console.log(data);
 
 Auth tokens and base URLs (including self-hosted and region URLs) are documented at https://docs.sentry.io/api/auth/.
 
+## Error handling
+
+Every operation with documented error responses has a generated `narrowError_<operation>` wrapper. ...
result
{"body":"### Summary\n\nThe generated `@sentry/api` client does not surface typed error responses. Callers only get a thrown value of type `unknown`, so consumers must guard with a broad `instanceof`/heuristic catch and cannot discriminate *which* error a given operation can return. Modeling error responses in the schema (per-operation typed error unions) would let consumers handle failures precisely instead of swallowing an `unknown`.\n\n### Motivation\n\nCame up while reviewing getsentry/cli#1318. There, a slug→project-ID resolution needs to distinguish two failure classes:\n\n- **User-actionable** (auth expired, host/scope error, 404 not-found) → fail the command with a clear message.\n- **Transient/unexpected** (e.g. a 500) → degrade gracefully and fall back to slug-based query scoping.\n\nBecause the client has no typed error surface, the CLI approximates this with its *own* error hierarchy and a catch-all:\n\n```ts\ntry {\n  return await fetchProjectId(org, project);\n} catch ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/error-results.gen.ts</path>
<type>file</type>
<content>
1: // This file is auto-generated by scripts/generate-error-results.mjs
2: // Do not edit directly. Re-run `bun run build` to regenerate.
3: 
4: import type { NarrowedResult, SdkResult } from './sentry-errors';
5: import { narrowError } from './sentry-errors';
6: import type { Options } from './sdk.gen';
7: import {
8:     addOrganizationMember,
9:     addOrganizationMemberTeam,
10:     addProjectSymbolSource,
11:     addProjectTeam,
12:     createOrganizationDashboard,
13:     createOrganizationDiscoverSavedQuery,
14:     createOrganizationExternalUser,
15:     createOrganizationForwarding,
16:     createOrganizationIssueIntegration,
17:     createOrganizationMonitor,
18:     createOrganizationNotificationsAction,
19:     createOrganizationProject,
20:     createOrganizationProjectDetector,
21:     createOrganizationRelease,
22:     createOrganizationReleaseDeploy,
23:     ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/package.json</path>
<type>file</type>
<content>
1: {
2:   "name": "@sentry/api",
3:   "version": "0.253.0",
4:   "description": "Official auto-generated TypeScript client for the Sentry public REST API",
5:   "keywords": [
6:     "sentry",
7:     "sentry-api",
8:     "openapi",
9:     "typescript",
10:     "api-client"
11:   ],
12:   "license": "FSL-1.1-Apache-2.0",
13:   "type": "module",
14:   "module": "dist/index.js",
15:   "types": "dist/index.d.ts",
16:   "files": [
17:     "dist"
18:   ],
19:   "scripts": {
20:     "build": "node build.mjs",
21:     "test": "bun test",
22:     "typecheck": "tsc -p tsconfig.test.json"
23:   },
24:   "exports": {
25:     ".": {
26:       "import": "./dist/index.js",
27:       "types": "./dist/index.d.ts"
28:     },
29:     "./zod": {
30:       "import": "./dist/zod.js",
31:       "types": "./dist/zod.d.ts"
32:     },
33:     "./browser": {
34:       "import": "./dist/browser.js",
35:       "types": ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/scripts/generate-error-results.mjs</path>
<type>file</type>
<content>
1: /**
2:  * Generate one status-discriminated result wrapper for every SDK operation
3:  * that declares an error response in OpenAPI.
4:  */
5: 
6: import { existsSync, readFileSync, writeFileSync } from "node:fs";
7: import { dirname, join, resolve } from "node:path";
8: import { fileURLToPath } from "node:url";
9: 
10: const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
11: const normalizedSpec = join(root, "openapi-normalized.json");
12: const specPath = existsSync(normalizedSpec)
13:   ? normalizedSpec
14:   : join(root, "openapi-derefed.json");
15: const spec = JSON.parse(readFileSync(specPath, "utf8"));
16: const sdkSource = readFileSync(join(root, "src", "sdk.gen.ts"), "utf8");
17: 
18: const errorRoutes = new Map();
19: for (const [path, methods] of Object.entries(spec.paths ?? {})) {
20:   for (const [method, operation] of ...
gateway · 2026-08-06 13:33:08
result
<path>/home/byk/Code/getsentry/sentry-api-schema/lib/sentry-errors.ts</path>
<type>file</type>
<content>
1: /**
2:  * The generated SDK's non-throwing result shape.
3:  *
4:  * Defined locally so the hand-written helpers never import generated code.
5:  */
6: export type SdkResult<TData = unknown, TError = unknown> =
7:   | {
8:       data: TData;
9:       error: undefined;
10:       request: Request;
11:       response: Response;
12:     }
13:   | {
14:       data: undefined;
15:       error: TError;
16:       request: Request;
17:       response: Response | undefined;
18:     };
19: 
20: type ErrorStatus<TErrorMap> = Extract<keyof TErrorMap, number>;
21: 
22: /** An API error whose status and body were declared by the operation. ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/client/client.gen.ts</path>
<type>file</type>
<content>
1: // This file is auto-generated by @hey-api/openapi-ts
2: 
3: import { createSseClient } from '../core/serverSentEvents.gen';
4: import type { HttpMethod } from '../core/types.gen';
5: import { getValidRequestBody } from '../core/utils.gen';
6: import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen';
7: import {
8:   buildUrl,
9:   createConfig,
10:   createInterceptors,
11:   getParseAs,
12:   mergeConfigs,
13:   mergeHeaders,
14:   setAuthParams,
15: } from './utils.gen';
16: 
17: type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
18:   body?: any;
19:   headers: ReturnType<typeof mergeHeaders>;
20: };
21: 
22: export const createClient = (config: Config = {}): Client => {
23:   let _config = mergeConfigs(createConfig(), config);
24: 
25:   const getConfig = (): Config => ({ ..._config });
26: 
27:   const setConfig = (config: ...
result
Found 12 matches
/home/byk/Code/getsentry/sentry-api-schema/src/core/serverSentEvents.gen.ts:
  Line 225:       } catch (error) {


/home/byk/Code/getsentry/sentry-api-schema/src/client/types.gen.ts:
  Line 53:   throwOnError?: T['throwOnError'];

  Line 65:       throwOnError: ThrowOnError;

  Line 98: export type RequestResult<

  Line 136:   throwOnError?: boolean;

  Line 146: ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;

  Line 165: ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;


/home/byk/Code/getsentry/sentry-api-schema/src/client/index.ts:
  Line 20:   RequestResult,


/home/byk/Code/getsentry/sentry-api-schema/src/client/client.gen.ts:
  Line 92:     } catch (error) {

  Line 104:       if (opts.throwOnError) {

  Line 114:             response: undefined as any,

  Line 224:     if (opts.throwOnError) {
result
Found 3 matches
/home/byk/Code/getsentry/sentry-api-schema/src/sdk.gen.ts:
  Line 1778: export const getProject = <ThrowOnError extends boolean = false>(options: Options<GetProjectData, ThrowOnError>) => (options.client ?? client).get<GetProjectResponses, GetProjectErrors, ThrowOnError>({


/home/byk/Code/getsentry/sentry-api-schema/src/types.gen.ts:
  Line 26780: export type GetProjectErrors = {

  Line 26791: export type GetProjectResponses = {
result
Found 15 matches
/home/byk/Code/getsentry/sentry-api-schema/src/error-results.gen.ts:
  Line 1671: export const narrowError_getProject = async (

  Line 1680: export const narrowError_getProjectEnvironment = async (

  Line 1689: export const narrowError_getProjectEvent = async (

  Line 1698: export const narrowError_getProjectEventAttachment = async (

  Line 1707: export const narrowError_getProjectEventSourceMapDebug = async (

  Line 1716: export const narrowError_getProjectHook = async (

  Line 1725: export const narrowError_getProjectInstallableBuildLatest = async (

  Line 1734: export const narrowError_getProjectKey = async (

  Line 1743: export const narrowError_getProjectMonitor = async (

  Line 1752: export const narrowError_getProjectPreprodSizeAnalysisStatusCheckRules = async (

  Line 1761: export const narrowError_getProjectPreprodSnapshotStatusCheckRules = async (

  Line 1770: export const narrowError_getProjectProfilingProfile = async (

  Line 1779: export const ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/build.mjs</path>
<type>file</type>
<content>
1: import { createClient } from "@hey-api/openapi-ts";
2: import { cpSync, appendFileSync, writeFileSync } from "node:fs";
3: import { execSync } from "node:child_process";
4: import { fileURLToPath } from "node:url";
5: import { dirname, join } from "node:path";
6: import { normalizeSpec } from "./lib/normalize-spec.mjs";
7: 
8: const __dirname = dirname(fileURLToPath(import.meta.url));
9: 
10: // 0.5 Normalize verbose English sentence operationIds to short REST-conventional
11: //     identifiers (e.g. "List Your Organizations" → "listOrganizations").
12: //     Writes a temporary openapi-normalized.json that the generator reads instead
13: //     of the source spec. The source spec is never modified.
14: //     OperationIds that are already identifiers (no spaces) are left untouched —
15: //     those were set intentionally via @extend_schema(operation_id=...).
16: ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/test/smoke.test.ts</path>
<type>file</type>
<content>
1: /**
2:  * Smoke tests for the public surface area.
3:  *
4:  * These tests don't hit the network — they assert that:
5:  *   1. The Link-header parser handles real Sentry response shapes correctly.
6:  *   2. The pagination helpers compose with mocked SDK results.
7:  *   3. The generated wrappers (pagination.gen.ts) export the expected names
8:  *      and have the correct type shape (compile-time check via `as`).
9:  *
10:  * Run with `bun test`.
11:  */
12: 
13: import { describe, expect, test } from "bun:test";
14: import {
15:   fetchPage,
16:   fetchPage_listOrganizationIssues,
17:   fetchPage_listOrganizations,
18:   narrowError,
19:   paginateAll,
20:   paginateAll_listOrganizations,
21:   paginateUpTo,
22:   paginateUpTo_listOrganizations,
23:   parseSentryLinkHeader,
24:   SentryApiError,
25:   unwrapPaginatedResult,
26:   unwrapResult,
27: } from "../src/index";
28: // ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/test/typecheck.ts</path>
<type>file</type>
<content>
150:   const result = await paginateUpTo_listOrganizationIssues(
151:     {
152:       ...config,
153:       path: { organization_id_or_slug: "my-org" },
154:     },
155:     {
156:       limit: 250,
157:       keepCursorOnOvershoot: true,
158:     },
159:   );
160:   void result.data;
161:   if (result.nextCursor) {
162:     const _: string = result.nextCursor;
163:   }
164: }
165: 
166: void fetchPageHappyPath;
167: void fetchPageRejectsCursor;
168: void fetchPageRequiresPath;
169: void paginateAllHappyPath;
170: void paginateUpToHappyPath;
171: void fetchPageCompoundOp;
172: void perPageAcceptedEvenWhenSpecOmitsIt;
173: void paginateUpToKeepCursorOnOvershoot;
174: 
175: // =====================================================================
176: // narrowError — status-discriminated, non-throwing error handling
177: // ...
gateway · 2026-08-06 13:33:53
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/sdk.gen.ts</path>
<type>file</type>
<content>
1758: 
1759: /**
1760:  * Delete a Project
1761:  *
1762:  * Schedules a project for deletion.
1763:  *
1764:  * Deletion happens asynchronously and therefore is not immediate. However once deletion has
1765:  * begun the state of a project changes and will be hidden from most public views.
1766:  */
1767: export const deleteProject = <ThrowOnError extends boolean = false>(options: Options<DeleteProjectData, ThrowOnError>) => (options.client ?? client).delete<DeleteProjectResponses, DeleteProjectErrors, ThrowOnError>({
1768:     security: [{ scheme: 'bearer', type: 'http' }],
1769:     url: '/api/0/projects/{organization_id_or_slug}/{project_id_or_slug}/',
1770:     ...options
1771: });
1772: 
1773: /**
1774:  * Retrieve a Project
1775:  *
1776:  * Return details on an individual project. ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/types.gen.ts</path>
<type>file</type>
<content>
26765:     body?: never;
26766:     path: {
26767:         /**
26768:          * The ID or slug of the organization the resource belongs to.
26769:          */
26770:         organization_id_or_slug: string;
26771:         /**
26772:          * The ID or slug of the project the resource belongs to. Project slugs are unique within each organization.
26773:          */
26774:         project_id_or_slug: string;
26775:     };
26776:     query?: never;
26777:     url: '/api/0/projects/{organization_id_or_slug}/{project_id_or_slug}/';
26778: };
26779: 
26780: export type GetProjectErrors = {
26781:     /**
26782:      * Forbidden
26783:      */
26784:     403: unknown;
26785:     /**
26786:      * Not Found
26787:      */
26788:     404: unknown;
26789: };
26790: 
26791: export type GetProjectResponses = {
26792:     200: {
26793:         stats?: unknown;
26794:         transactionStats?: ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/client/types.gen.ts</path>
<type>file</type>
<content>
40:    */
41:   parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';
42:   /**
43:    * Should we return only data or multiple fields (data, error, response, etc.)?
44:    *
45:    * @default 'fields'
46:    */
47:   responseStyle?: ResponseStyle;
48:   /**
49:    * Throw an error instead of returning it in the response?
50:    *
51:    * @default false
52:    */
53:   throwOnError?: T['throwOnError'];
54: }
55: 
56: export interface RequestOptions<
57:   TData = unknown,
58:   TResponseStyle extends ResponseStyle = 'fields',
59:   ThrowOnError extends boolean = boolean,
60:   Url extends string = string,
61: >
62:   extends
63:     Config<{
64:       responseStyle: TResponseStyle;
65:       throwOnError: ThrowOnError;
66:     }>,
67:     Pick<
68:       ServerSentEventsOptions<TData>,
69:       | 'onSseError'
70:       | 'onSseEvent'
71:       | ...
result
Ripgrep JSON record exceeded 65536 bytes
result
Found 100 matches (more matches available)
/home/byk/Code/getsentry/sentry-api-schema/src/types.gen.ts:
  Line 8:  * Response type for the POST endpoint (default kickoff and step paths).

  Line 64:      * - `eventTypes`: Any of `error` or `default`.

  Line 71:      * "eventTypes": ["default", "error"],

  Line 80:      * - `eventTypes`: Any of `error` or `default`.

  Line 87:      * "eventTypes": ["default", "error"],

  Line 1418:          * * `default`

  Line 1421:         legend_type?: 'default' | 'breakdown' | null;

  Line 1588:          * * `default`

  Line 1591:         legend_type?: 'default' | 'breakdown' | null;

  Line 1739:         legendType: 'default' | 'breakdown' | null;

  Line 1958:      * * `default`

  Line 1961:     legend_type?: 'default' | 'breakdown' | null;

  Line 2270:     defaultEnvironment: string | null;

  Line 2378:      * - default

  Line 2652:         type: 'default' | 'error' | 'csp' | 'nel' | 'hpkp' | 'expectct' | 'expectstaple' | ...
result
Found 7 matches
/home/byk/Code/getsentry/sentry-api-schema/package.json:
  Line 20:     "build": "node build.mjs",


/home/byk/Code/getsentry/sentry-api-schema/build.mjs:
  Line 46: execSync(`node ${JSON.stringify(join(__dirname, "scripts", "generate-pagination.mjs"))}`, { stdio: "inherit" });

  Line 47: execSync(`node ${JSON.stringify(join(__dirname, "scripts", "generate-error-results.mjs"))}`, { stdio: "inherit" });

  Line 75: execSync("bun build src/index.ts --outdir dist", { stdio: "inherit" });

  Line 76: execSync('bun build src/zod.ts --outdir dist --external zod', { stdio: "inherit" });

  Line 77: execSync("bun build src/browser.ts --outdir dist", { stdio: "inherit" });

  Line 78: execSync("tsc --emitDeclarationOnly", { stdio: "inherit" });
result
$ tsc -p tsconfig.test.json
Volta error: Node is not available.

To run any Node command, first set a default version using `volta install node`
Error details written to /home/byk/.volta/log/volta-error-2026-08-06_13_34_25.260.log
error: script "typecheck" exited with code 126
gateway · 2026-08-06 13:35:32
result
Found 2 matches
/home/byk/Code/getsentry/sentry-api-schema/src/sdk.gen.ts:
  Line 27: export const listOrganizations = <ThrowOnError extends boolean = false>(options?: Options<ListOrganizationsData, ThrowOnError>) => (options?.client ?? client).get<ListOrganizationsResponses, ListOrganizationsErrors, ThrowOnError>({

  Line 2617: export const listSeerModels = <ThrowOnError extends boolean = false>(options?: Options<ListSeerModelsData, ThrowOnError>) => (options?.client ?? client).get<ListSeerModelsResponses, unknown, ThrowOnError>({
result
Found 1 matches
/home/byk/Code/getsentry/sentry-api-schema/src/error-results.gen.ts:
  Line 2068:     options?: Options<ListOrganizationsData, false>,
result
Found 1 matches
/home/byk/Code/getsentry/sentry-api-schema/src/sdk.gen.ts:
  Line 7: export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options2<TData, ThrowOnError> & {
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/error-results.gen.ts</path>
<type>file</type>
<content>
1658:         [401, 403, 404],
1659:     );
1660: 
1661: /** Call `getOrganizationWorkflow` and preserve its documented status-to-body error map. */
1662: export const narrowError_getOrganizationWorkflow = async (
1663:     options: Options<GetOrganizationWorkflowData, false>,
1664: ): Promise<NarrowedResult<GetOrganizationWorkflowResponses[keyof GetOrganizationWorkflowResponses], GetOrganizationWorkflowErrors>> =>
1665:     narrowError<GetOrganizationWorkflowResponses[keyof GetOrganizationWorkflowResponses], GetOrganizationWorkflowErrors>(
1666:         await getOrganizationWorkflow(options),
1667:         [400, 401, 403, 404],
1668:     );
1669: 
1670: /** Call `getProject` and preserve its documented status-to-body error map. ...
result
bun test v1.3.14 (0d9b296a)

 94 pass
 0 fail
 183 expect() calls
Ran 94 tests across 3 files. [200.00ms]
result
diff --git a/lib/sentry-errors.ts b/lib/sentry-errors.ts
new file mode 100644
index 0000000..85fc095
--- /dev/null
+++ b/lib/sentry-errors.ts
@@ -0,0 +1,130 @@
+/**
+ * The generated SDK's non-throwing result shape.
+ *
+ * Defined locally so the hand-written helpers never import generated code.
+ */
+export type SdkResult<TData = unknown, TError = unknown> =
+  | {
+      data: TData;
+      error: undefined;
+      request: Request;
+      response: Response;
+    }
+  | {
+      data: undefined;
+      error: TError;
+      request: Request;
+      response: Response | undefined;
+    };
+
+type ErrorStatus<TErrorMap> = Extract<keyof TErrorMap, number>;
+
+/** An API error whose status and body were declared by the operation. ...
gateway · 2026-08-06 13:35:43
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/sdk.gen.ts</path>
<type>file</type>
<content>
1: // This file is auto-generated by @hey-api/openapi-ts
2: 
3: import { type Client, formDataBodySerializer, type Options as Options2, type TDataShape } from './client';
4: import { client } from './client.gen';
5: import type { AddOrganizationMemberData, AddOrganizationMemberErrors, AddOrganizationMemberResponses, AddOrganizationMemberTeamData, AddOrganizationMemberTeamErrors, AddOrganizationMemberTeamResponses, AddProjectSymbolSourceData, AddProjectSymbolSourceErrors, AddProjectSymbolSourceResponses, AddProjectTeamData, AddProjectTeamErrors, AddProjectTeamResponses, CreateOrganizationDashboardData, CreateOrganizationDashboardErrors, CreateOrganizationDashboardResponses, CreateOrganizationDiscoverSavedQueryData, CreateOrganizationDiscoverSavedQueryErrors, CreateOrganizationDiscoverSavedQueryResponses, CreateOrganizationExternalUserData, CreateOrganizationExternalUserErrors, ...
result
No files found
result
Found 1 matches
/home/byk/Code/getsentry/sentry-api-schema/src/client/utils.gen.ts:
  Line 308: export const createConfig = <T extends ClientOptions = ClientOptions>(
result
Ripgrep JSON record exceeded 65536 bytes
result
No files found
result
Found 1 matches
/home/byk/Code/getsentry/sentry-api-schema/src/error-results.gen.ts:
  Line 4: import type { NarrowedResult, SdkResult } from './sentry-errors';
gateway · 2026-08-06 13:35:53
result
Found 1 matches
/home/byk/Code/getsentry/sentry-api-schema/src/client/types.gen.ts:
  Line 204: export type Options<
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/client/utils.gen.ts</path>
<type>file</type>
<content>
295:     explode: true,
296:     style: 'form',
297:   },
298:   object: {
299:     explode: true,
300:     style: 'deepObject',
301:   },
302: });
303: 
304: const defaultHeaders = {
305:   'Content-Type': 'application/json',
306: };
307: 
308: export const createConfig = <T extends ClientOptions = ClientOptions>(
309:   override: Config<Omit<ClientOptions, keyof T> & T> = {},
310: ): Config<Omit<ClientOptions, keyof T> & T> => ({
311:   ...jsonBodySerializer,
312:   headers: defaultHeaders,
313:   parseAs: 'auto',
314:   querySerializer: defaultQuerySerializer,
315:   ...override,
316: });

(End of file - total 316 lines)
</content>
result
<path>/home/byk/Code/getsentry/sentry-api-schema/tsconfig.json</path>
<type>file</type>
<content>
1: {
2:   "compilerOptions": {
3:     "lib": ["ESNext", "DOM"],
4:     "target": "ESNext",
5:     "module": "ESNext",
6:     "moduleDetection": "force",
7:     "allowJs": true,
8:     "moduleResolution": "bundler",
9:     "allowImportingTsExtensions": true,
10:     "verbatimModuleSyntax": true,
11:     "declaration": true,
12:     "emitDeclarationOnly": true,
13:     "outDir": "dist",
14:     "resolveJsonModule": true,
15:     "strict": true,
16:     "skipLibCheck": true,
17:     "noFallthroughCasesInSwitch": true,
18:     "noUncheckedIndexedAccess": true,
19:     "noImplicitOverride": true,
20:     "esModuleInterop": true,
21:     "forceConsistentCasingInFileNames": true,
22:     "noUnusedLocals": false,
23:     "noUnusedParameters": false,
24:     "noPropertyAccessFromIndexSignature": false
25:   },
26:   "include": ["src/**/*.ts"],
27:   "exclude": ["node_modules", "dist"]
28: }

(End ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/tsconfig.test.json</path>
<type>file</type>
<content>
1: {
2:   "extends": "./tsconfig.json",
3:   "compilerOptions": {
4:     "noEmit": true,
5:     "emitDeclarationOnly": false,
6:     "types": ["bun"]
7:   },
8:   "include": ["src/**/*.ts", "test/**/*.ts"]
9: }

(End of file - total 9 lines)
</content>
result
/home/byk/.volta/bin/node
/home/byk/.volta/bin/bun
Volta error: Node is not available.

To run any Node command, first set a default version using `volta install node`
Error details written to /home/byk/.volta/log/volta-error-2026-08-06_13_35_53.112.log
gateway · 2026-08-06 13:35:59
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/client/types.gen.ts</path>
<type>file</type>
<content>
195:   body?: unknown;
196:   headers?: unknown;
197:   path?: unknown;
198:   query?: unknown;
199:   url: string;
200: }
201: 
202: type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
203: 
204: export type Options<
205:   TData extends TDataShape = TDataShape,
206:   ThrowOnError extends boolean = boolean,
207:   TResponse = unknown,
208:   TResponseStyle extends ResponseStyle = 'fields',
209: > = OmitKeys<
210:   RequestOptions<TResponse, TResponseStyle, ThrowOnError>,
211:   'body' | 'path' | 'query' | 'url'
212: > &
213:   ([TData] extends [never] ? unknown : Omit<TData, 'url'>);

(End of file - total 213 lines)
</content>
result
<path>/home/byk/Code/getsentry/sentry-api-schema/src/index.ts</path>
<type>file</type>
<content>
1: // This file is auto-generated by @hey-api/openapi-ts
2: 
3: export { addOrganizationMember, addOrganizationMemberTeam, addProjectSymbolSource, addProjectTeam, createOrganizationDashboard, createOrganizationDiscoverSavedQuery, createOrganizationExternalUser, createOrganizationForwarding, createOrganizationIssueIntegration, createOrganizationMonitor, createOrganizationNotificationsAction, createOrganizationProject, createOrganizationProjectDetector, createOrganizationRelease, createOrganizationReleaseDeploy, createOrganizationSpikeProtection, createOrganizationTeam, createOrganizationWorkflow, createProjectHook, createProjectKey, createProjectPreprodSizeAnalysisSkippedStatusCheck, createProjectPreprodSnapshotSkippedStatusCheck, createProjectReplayDeletionJob, createProjectUserFeedback, createSentryAppInstallationExternalIssue, createTeamExternalTeam, createTeamProject, ...
result
<path>/home/byk/Code/getsentry/sentry-api-schema/dist/error-results.gen.d.ts</path>
<type>file</type>
<content>
1: import type { NarrowedResult } from './sentry-errors';
2: import type { Options } from './sdk.gen';
3: import type { AddOrganizationMemberData, AddOrganizationMemberErrors, AddOrganizationMemberResponses, AddOrganizationMemberTeamData, AddOrganizationMemberTeamErrors, AddOrganizationMemberTeamResponses, AddProjectSymbolSourceData, AddProjectSymbolSourceErrors, AddProjectSymbolSourceResponses, AddProjectTeamData, AddProjectTeamErrors, AddProjectTeamResponses, CreateOrganizationDashboardData, CreateOrganizationDashboardErrors, CreateOrganizationDashboardResponses, CreateOrganizationDiscoverSavedQueryData, CreateOrganizationDiscoverSavedQueryErrors, CreateOrganizationDiscoverSavedQueryResponses, CreateOrganizationExternalUserData, CreateOrganizationExternalUserErrors, CreateOrganizationExternalUserResponses, CreateOrganizationForwardingData, ...
result
Found 15 matches
/home/byk/Code/getsentry/sentry-api-schema/dist/error-results.gen.d.ts:
  Line 185: export declare const narrowError_getProject: (options: Options<GetProjectData, false>) => Promise<NarrowedResult<GetProjectResponses[keyof GetProjectResponses], GetProjectErrors>>;

  Line 187: export declare const narrowError_getProjectEnvironment: (options: Options<GetProjectEnvironmentData, false>) => Promise<NarrowedResult<GetProjectEnvironmentResponses[keyof GetProjectEnvironmentResponses], GetProjectEnvironmentErrors>>;

  Line 189: export declare const narrowError_getProjectEvent: (options: Options<GetProjectEventData, false>) => Promise<NarrowedResult<GetProjectEventResponses[keyof GetProjectEventResponses], GetProjectEventErrors>>;

  Line 191: export declare const narrowError_getProjectEventAttachment: (options: Options<GetProjectEventAttachmentData, false>) => Promise<NarrowedResult<GetProjectEventAttachmentResponses[keyof GetProjectEventAttachmentResponses], ...
result
Found 4 matches
/home/byk/Code/getsentry/sentry-api-schema/test/typecheck.ts:
  Line 19:   narrowError_getProject,

  Line 180:   const res = await narrowError_getProject({

  Line 193:     // Includes unexpected HTTP statuses and transport failures.


/home/byk/Code/getsentry/sentry-api-schema/test/smoke.test.ts:
  Line 177:   test("represents transport failures without reading a missing response", () => {
gateway · 2026-08-06 13:37:04

Findings

High — Generated wrappers break with clients configured for non-default result behavior

narrowError_<operation> accepts a custom client, but never forces throwOnError: false or responseStyle: "fields" before calling the SDK (scripts/generate-error-results.mjs:82-87; generated example src/error-results.gen.ts:1671-1676).

An official client configured with:

  • throwOnError: true throws instead of returning NarrowedResult.
  • responseStyle: "data" returns raw data or undefined; narrowError then reads result.error and either crashes or reports malformed success data (lib/sentry-errors.ts:93-98).

The underlying behavior appears at src/client/client.gen.ts:104-115, src/client/client.gen.ts:224-234, while global configuration permits both settings at src/client/types.gen.ts:133-136.

The wrappers must override both settings at the call site, regardless of client defaults.

High — Transport failures while reading the response body escape instead of becoming SentryApiTransportError

The client catches only the initial fetch() rejection (src/client/client.gen.ts:90-116). Body reads happen outside that try:

  • successful JSON body: src/client/client.gen.ts:171-175
  • error body: src/client/client.gen.ts:204-213

A connection failure after headers arrive makes response.text() reject. The generated wrapper directly awaits the SDK call (scripts/generate-error-results.mjs:85-87), so its promise rejects rather than returning { ok: false, error: SentryApiTransportError }.

The current transport test manually constructs a result with response: undefined (test/smoke.test.ts:177-190); it never exercises the real client or generated wrapper and therefore misses this path.

Medium — The exported hand-written API changes incompatibly

SentryApiError previously used the body type as its first generic and accepted (status, body, response, message?). ...

gpt-5.6-sol · 2026-08-06 13:37:04 · ~711 tokens