Skip to content

Commit f6eccc4

Browse files
authored
fix(sveltekit): Avoid capturing "Not Found" errors in server handleError wrapper (#7898)
Incoming page load requests on the server side for unknown/invalid routes will throw a `Error: Not found: /unknown/route` error in the server `handleError` hook. In our wrapper, we don't want to catch these errors (similarly to 404 errors in the `wrapLoadWithSentry` wrapper).
1 parent 3040a6b commit f6eccc4

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

packages/sveltekit/src/server/handleError.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ function defaultErrorHandler({ error }: Parameters<HandleServerError>[0]): Retur
2121
*/
2222
export function handleErrorWithSentry(handleError: HandleServerError = defaultErrorHandler): HandleServerError {
2323
return (input: { error: unknown; event: RequestEvent }): ReturnType<HandleServerError> => {
24+
if (isNotFoundError(input)) {
25+
return handleError(input);
26+
}
27+
2428
captureException(input.error, scope => {
2529
scope.addEventProcessor(event => {
2630
addExceptionMechanism(event, {
@@ -35,3 +39,25 @@ export function handleErrorWithSentry(handleError: HandleServerError = defaultEr
3539
return handleError(input);
3640
};
3741
}
42+
43+
/**
44+
* When a page request fails because the page is not found, SvelteKit throws a "Not found" error.
45+
* In the error handler here, we can't access the response yet (which we do in the load instrumentation),
46+
* so we have to check if the error is a "Not found" error by checking if the route id is missing and
47+
* by checking the error message on top of the raw stack trace.
48+
*/
49+
function isNotFoundError(input: { error: unknown; event: RequestEvent }): boolean {
50+
const { error, event } = input;
51+
52+
const hasNoRouteId = !event.route || !event.route.id;
53+
54+
const rawStack: string =
55+
(error != null &&
56+
typeof error === 'object' &&
57+
'stack' in error &&
58+
typeof error.stack === 'string' &&
59+
error.stack) ||
60+
'';
61+
62+
return hasNoRouteId && rawStack.startsWith('Error: Not found:');
63+
}

packages/sveltekit/test/server/handleError.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,23 @@ describe('handleError', () => {
4747
mockScope = new Scope();
4848
});
4949

50+
it('doesn\'t capture "Not found" errors for incorrect navigations', async () => {
51+
const wrappedHandleError = handleErrorWithSentry();
52+
const mockError = new Error('Not found: /asdf/123');
53+
const mockEvent = {
54+
url: new URL('https://myDomain.com/asdf/123'),
55+
route: { id: null }, // <-- this is what SvelteKit puts in the event when the page is not found
56+
// ...
57+
} as RequestEvent;
58+
59+
const returnVal = await wrappedHandleError({ error: mockError, event: mockEvent });
60+
61+
expect(returnVal).not.toBeDefined();
62+
expect(mockCaptureException).toHaveBeenCalledTimes(0);
63+
expect(mockAddExceptionMechanism).toHaveBeenCalledTimes(0);
64+
expect(consoleErrorSpy).toHaveBeenCalledTimes(1);
65+
});
66+
5067
describe('calls captureException', () => {
5168
it('invokes the default handler if no handleError func is provided', async () => {
5269
const wrappedHandleError = handleErrorWithSentry();

0 commit comments

Comments
 (0)