Skip to content

Commit 9a9ae1c

Browse files
committed
ref(sveltekit): Improve SvelteKit 2.0 Not Found error handling
1 parent 8fb1a2f commit 9a9ae1c

File tree

3 files changed

+424
-89
lines changed

3 files changed

+424
-89
lines changed

packages/sveltekit/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232
"sorcery": "0.11.0"
3333
},
3434
"devDependencies": {
35-
"@sveltejs/kit": "^1.11.0",
35+
"@sveltejs/kit": "^2.0.2",
3636
"rollup": "^3.20.2",
37-
"svelte": "^3.44.0",
38-
"vite": "4.0.5"
37+
"svelte": "^4.2.8",
38+
"vite": "^5.0.10"
3939
},
4040
"scripts": {
4141
"build": "run-p build:transpile build:types",

packages/sveltekit/src/server/handleError.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { captureException } from '@sentry/node';
2-
import type { HandleServerError, RequestEvent } from '@sveltejs/kit';
2+
import type { HandleServerError } from '@sveltejs/kit';
33

44
import { flushIfServerless } from './utils';
55

@@ -11,14 +11,28 @@ function defaultErrorHandler({ error }: Parameters<HandleServerError>[0]): Retur
1111
console.error(error && error.stack);
1212
}
1313

14+
type HandleServerErrorInput = Parameters<HandleServerError>[0];
15+
16+
/**
17+
* Backwards-compatible HandleServerError Input type for SvelteKit 1.x and 2.x
18+
* `message` and `status` were added in 2.x.
19+
* For backwards-compatibility, we make them optional
20+
*
21+
* @see https://kit.svelte.dev/docs/migrating-to-sveltekit-2#improved-error-handling
22+
*/
23+
type SafeHandleServerErrorInput = Omit<HandleServerErrorInput, 'status' | 'message'> &
24+
Partial<Pick<HandleServerErrorInput, 'status' | 'message'>>;
25+
1426
/**
1527
* Wrapper for the SvelteKit error handler that sends the error to Sentry.
1628
*
1729
* @param handleError The original SvelteKit error handler.
1830
*/
1931
export function handleErrorWithSentry(handleError: HandleServerError = defaultErrorHandler): HandleServerError {
20-
return async (input: { error: unknown; event: RequestEvent }): Promise<void | App.Error> => {
32+
return async (input: SafeHandleServerErrorInput): Promise<void | App.Error> => {
2133
if (isNotFoundError(input)) {
34+
// We're extra cautious with SafeHandleServerErrorInput - this type is not compatible with HandleServerErrorInput
35+
// @ts-expect-error - we're still passing the same object, just with a different (backwards-compatible) type
2236
return handleError(input);
2337
}
2438

@@ -31,6 +45,8 @@ export function handleErrorWithSentry(handleError: HandleServerError = defaultEr
3145

3246
await flushIfServerless();
3347

48+
// We're extra cautious with SafeHandleServerErrorInput - this type is not compatible with HandleServerErrorInput
49+
// @ts-expect-error - we're still passing the same object, just with a different (backwards-compatible) type
3450
return handleError(input);
3551
};
3652
}
@@ -41,9 +57,17 @@ export function handleErrorWithSentry(handleError: HandleServerError = defaultEr
4157
* so we have to check if the error is a "Not found" error by checking if the route id is missing and
4258
* by checking the error message on top of the raw stack trace.
4359
*/
44-
function isNotFoundError(input: { error: unknown; event: RequestEvent }): boolean {
45-
const { error, event } = input;
60+
function isNotFoundError(input: SafeHandleServerErrorInput): boolean {
61+
const { error, event, status, message } = input;
62+
63+
// SvelteKit 2.0 offers a reliable way to check for a Not Found error:
64+
if (status === 404 && message === 'Not Found') {
65+
return true;
66+
}
4667

68+
// SvelteKit 1.x doesn't offer a reliable way to check for a Not Found error.
69+
// So we check the route id (shouldn't exist) and the raw stack trace
70+
// We can delete all of this below whenever we drop Kit 1.x support
4771
const hasNoRouteId = !event.route || !event.route.id;
4872

4973
const rawStack: string =

0 commit comments

Comments
 (0)