Skip to content

captureRemixServerException throws error due to expecting instance of ErrorResponseImpl but receiving original Response thrown from loader #10160

@robmonie

Description

@robmonie

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/remix

SDK Version

7.93.0

Framework Version

Remix 2.4.0

Link to Sentry event

No response

SDK Setup

//entry.server.tsx

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  release: process.env.SENTRY_RELEASE,
  environment: process.env.ENVIRONMENT,
  tracesSampleRate: 1,
  integrations: [],
  debug: true,
  beforeSend: (event, hint) => {
    if (isDev) {
      // eslint-disable-next-line no-console
      console.error(hint.originalException || hint.syntheticException);
      return null; // this drops the event and nothing will be sent to sentry
    }

    return event;
  },
});

//entry.client.tsx

Sentry.init({
  dsn: window.ENV.sentryDsn,
  release: window.ENV.sentryRelease,
  environment: window.ENV.environment,
  tracesSampleRate: 1.0,
  integrations: [
    new Sentry.BrowserTracing({
      routingInstrumentation: Sentry.remixRouterInstrumentation(useEffect, useLocation, useMatches),
    }),
  ],
  beforeSend: (event, hint) => {
    if (isDev) {
      // eslint-disable-next-line no-console
      console.error(hint.originalException || hint.syntheticException);
      return null; // this drops the event and nothing will be sent to sentry
    }

    return event;
  },
});

Steps to Reproduce

  1. Configure a Remix Express server with the wrapped request handler:
app.all(
  '*',
  wrapExpressCreateRequestHandler(createRequestHandler)({
    build: serverBuild,
    mode: process.env.NODE_ENV,
  }),
);

Throw a 500 Response from a loader

eg:

throw new Response(null, {
    status: 500,
    statusText: 'Not found',
  });
  1. Load the page that triggers the loader. This will throw an error from within captureRemixServerException. Upon inspection, this appears to be due to the fact that the error passed to captureRemixServerException is the original Response object thrown above, not an instance of ErrorResponseImpl which seems to be what's expected. It therefore fails the test isRouteErrorResponse and continues on.

fails both of these tests...

if (IS_REMIX_V2 && response.isRouteErrorResponse(err) && err.status < 500) {
    return;
  }

  if (response.isResponse(err) && err.status < 500) {
    return;
  }

The log output from sentry with debugging turned on is as follows and shows the stack trace among other warnings.

[MyApp] Sentry Logger [log]: [Tracing] starting http.server transaction - routes/test.$id
[MyApp] Sentry Logger [log]: [Tracing] Starting 'function.remix.loader' span on transaction 'root' (8e82569d1d8c5762).
[MyApp] Sentry Logger [log]: [Tracing] Starting 'function.remix.loader' span on transaction 'routes/test.$id' (8e82569d1d8c5762).
[MyApp] Sentry Logger [warn]: Failed to normalize Remix request
[MyApp] Sentry Logger [log]: Failed to add non-enumerable property "__sentry_captured__" to object
[MyApp] Error:
[MyApp]     at Hub.captureException (/Users/robmonie/dev/my-app/node_modules/@sentry/src/hub.ts:271:32)
[MyApp]     at Object.captureException (/Users/robmonie/dev/my-app/node_modules/@sentry/src/exports.ts:47:26)
[MyApp]     at captureRemixServerException (/Users/robmonie/dev/my-app/node_modules/@sentry/src/utils/instrumentServer.ts:147:11)
[MyApp]     at processTicksAndRejections (node:internal/process/task_queues:95:5)
[MyApp]     at /Users/robmonie/dev/my-app/node_modules/@sentry/src/utils/instrumentServer.ts:282:36
[MyApp]     at Object.callRouteLoaderRR (/Users/robmonie/dev/my-app/node_modules/@remix-run/server-runtime/dist/data.js:52:16)
[MyApp]     at callLoaderOrAction (/Users/robmonie/dev/my-app/node_modules/@remix-run/server-runtime/node_modules/@remix-run/router/router.ts:4014:16)
[MyApp]     at async Promise.all (index 2)
[MyApp]     at loadRouteData (/Users/robmonie/dev/my-app/node_modules/@remix-run/server-runtime/node_modules/@remix-run/router/router.ts:3290:19)
[MyApp]     at queryImpl (/Users/robmonie/dev/my-app/node_modules/@remix-run/server-runtime/node_modules/@remix-run/router/router.ts:3068:20)
[MyApp] Sentry Logger [log]: before send for type `error` returned `null`, will not send event.
[MyApp] Sentry Logger [log]: [Tracing] Starting 'function.remix.document_request' span on transaction 'routes/test.$id' (8e82569d1d8c5762).
[MyApp] Sentry Logger [log]: [Tracing] Finishing http.server transaction: routes/test.$id.
[MyApp] Sentry Logger [error]: Transport disabled
[MyApp] Sentry Logger [log]: Flushing events...
[MyApp] Sentry Logger [log]: Done flushing events


Note that in our app's ErrorBoundary we check the error with isRouteErrorResponse and by that point, the error has been converted by remix to an instance of an ErrorResponseImpl.

Expected Result

Expect the 500 error to be capture, parsed and reported to sentry

Actual Result

Sentry throws exception as detailed above.

Metadata

Metadata

Assignees

Labels

BugPackage: remixIssues related to the Sentry Remix SDK

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions