Skip to content

Commit ce67a38

Browse files
authored
fix(remix): Skip capturing ok responses as errors. (getsentry#5405)
[Remix supports throwing responses from `loader` and `action` functions for its internal `CatchBoundary`](https://remix.run/docs/en/v1/api/conventions#throwing-responses-in-loaders). They are [catched on the caller level](https://github.com/remix-run/remix/blob/7688da5c75190a2e29496c78721456d6e12e3abe/packages/remix-server-runtime/data.ts#L41-L49), but as we wrap the callees, they are registered as exceptions in the SDK. Being http responses, they end up like `{size: 0}`, which is not meaningful. This PR skips exception capturing for responses that are not `4xx` or `5xx`.
1 parent 2c6683f commit ce67a38

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

packages/remix/src/utils/instrumentServer.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,41 @@ interface DataFunction {
6969
(args: DataFunctionArgs): Promise<Response> | Response | Promise<AppData> | AppData;
7070
}
7171

72+
// Taken from Remix Implementation
73+
// https://github.com/remix-run/remix/blob/7688da5c75190a2e29496c78721456d6e12e3abe/packages/remix-server-runtime/responses.ts#L54-L62
74+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
75+
function isResponse(value: any): value is Response {
76+
return (
77+
value != null &&
78+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
79+
typeof value.status === 'number' &&
80+
typeof value.statusText === 'string' &&
81+
typeof value.headers === 'object' &&
82+
typeof value.body !== 'undefined'
83+
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
84+
);
85+
}
86+
87+
// Taken from Remix Implementation
88+
// https://github.com/remix-run/remix/blob/7688da5c75190a2e29496c78721456d6e12e3abe/packages/remix-server-runtime/data.ts#L131-L145
89+
function extractData(response: Response): Promise<unknown> {
90+
const contentType = response.headers.get('Content-Type');
91+
92+
if (contentType && /\bapplication\/json\b/.test(contentType)) {
93+
return response.json();
94+
}
95+
96+
return response.text();
97+
}
98+
7299
function captureRemixServerException(err: Error, name: string): void {
73-
captureException(err, scope => {
100+
// Skip capturing if the thrown error is an OK Response
101+
// https://remix.run/docs/en/v1/api/conventions#throwing-responses-in-loaders
102+
if (isResponse(err) && err.status < 400) {
103+
return;
104+
}
105+
106+
captureException(isResponse(err) ? extractData(err) : err, scope => {
74107
scope.addEventProcessor(event => {
75108
addExceptionMechanism(event, {
76109
type: 'instrument',

0 commit comments

Comments
 (0)