-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix(sveltekit): Handle SvelteKit 3 error kinds in handleErrorWithSentry #23651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
...ges/e2e-tests/test-applications/sveltekit-3/src/routes/expected-error-4xx/+page.server.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { error } from '@sveltejs/kit'; | ||
|
|
||
| export const load = async () => { | ||
| // SvelteKit 3 passes expected errors to `handleError` as `kind: 'app'`. | ||
| // 4xx are expected, so the SDK must not capture them. | ||
| error(404, 'Expected 404 Error'); | ||
| }; |
1 change: 1 addition & 0 deletions
1
...ckages/e2e-tests/test-applications/sveltekit-3/src/routes/expected-error-4xx/+page.svelte
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| <h1>Expected 4xx error</h1> |
7 changes: 7 additions & 0 deletions
7
...ges/e2e-tests/test-applications/sveltekit-3/src/routes/expected-error-5xx/+page.server.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { error } from '@sveltejs/kit'; | ||
|
|
||
| export const load = async () => { | ||
| // SvelteKit 3 passes expected errors to `handleError` as `kind: 'app'`. | ||
| // 5xx are worth reporting, so the SDK captures them. | ||
| error(500, 'Expected 500 Error'); | ||
| }; |
1 change: 1 addition & 0 deletions
1
...ckages/e2e-tests/test-applications/sveltekit-3/src/routes/expected-error-5xx/+page.svelte
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| <h1>Expected 5xx error</h1> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| /** | ||
| * Where an error passed to `handleError` came from. Added in SvelteKit 3; `undefined` on | ||
| * SvelteKit 1.x and 2.x. | ||
| * | ||
| * - `app`: thrown with the `error(...)` helper | ||
| * - `framework`: generated by SvelteKit itself (404s, 405s, 413s, ...) | ||
| * - `validation`: invalid remote function arguments (server only) | ||
| * - `unknown`: thrown by user code, or code it calls | ||
| * | ||
| * @see https://svelte.dev/docs/kit/hooks#handleError | ||
| */ | ||
| export type CaughtErrorKind = 'app' | 'framework' | 'validation' | 'unknown'; | ||
|
|
||
| /** | ||
| * The `handleError` input as of SvelteKit 3, where errors are discriminated by `kind` and the | ||
| * status lives on the error instead of the input. | ||
| */ | ||
| export type CaughtErrorInput = { | ||
| kind: CaughtErrorKind; | ||
| error: unknown; | ||
| /** Only present for `kind: 'validation'` */ | ||
| issues?: unknown[]; | ||
| }; | ||
|
|
||
| /** | ||
| * The `handleError` input on SvelteKit 1.x and 2.x, which had no `kind` and carried the status and | ||
| * message on the input itself. | ||
| * | ||
| * SvelteKit 3 keeps both alive in dev builds as deprecated getters that log a warning when read. | ||
| * Modelling the two shapes as a discriminated union is what stops us reading them on a SvelteKit 3 | ||
| * input: as far as the type system is concerned, `status` doesn't exist there. | ||
| */ | ||
| export type LegacyCaughtErrorInput = { | ||
| kind?: undefined; | ||
| error: unknown; | ||
| status?: number; | ||
| message?: string; | ||
| }; | ||
|
|
||
| /** | ||
| * The input of a SvelteKit `handleError` hook, covering SvelteKit 1.x, 2.x and 3. | ||
| * | ||
| * We declare this structurally instead of importing SvelteKit's `HandleServerError`/ | ||
| * `HandleClientError`, because those types moved from `@sveltejs/kit` to `@sveltejs/kit/hooks` | ||
| * in SvelteKit 3 and neither import path type-checks against both majors. | ||
| */ | ||
| export type SentryHandleErrorInput = CaughtErrorInput | LegacyCaughtErrorInput; | ||
|
|
||
| /** The `handleError` input on the server, where we also read from the request event. */ | ||
| export type SentryHandleServerErrorInput = SentryHandleErrorInput & { | ||
| event: { | ||
| route?: { id?: string | null }; | ||
| platform?: unknown; | ||
| }; | ||
| }; | ||
|
|
||
| /** The `handleError` input on the client. */ | ||
| export type SentryHandleClientErrorInput = SentryHandleErrorInput & { | ||
| event: unknown; | ||
| }; | ||
|
|
||
| /** | ||
| * Constrains the user-provided `handleError` hook without depending on SvelteKit's own types. | ||
| * `never` as the parameter type accepts any single-argument function (parameters are | ||
| * contravariant), so a SvelteKit 1.x, 2.x or 3 hook all satisfy it. | ||
| */ | ||
| export type AnyErrorHandler = (input: never) => unknown; | ||
|
|
||
| /** | ||
| * Reads the HTTP status off an error. In SvelteKit 3, `app`, `framework` and `validation` errors | ||
| * all carry their status here. | ||
| */ | ||
| export function getErrorStatus(error: unknown): number | undefined { | ||
| if (error == null || typeof error !== 'object') { | ||
| return undefined; | ||
| } | ||
|
|
||
| const { status } = error as { status?: unknown }; | ||
|
|
||
| return typeof status === 'number' ? status : undefined; | ||
| } | ||
|
|
||
| /** | ||
| * Whether an error passed to `handleError` should be sent to Sentry. | ||
| * | ||
| * @param isExpectedLegacyError checks whether a SvelteKit 1.x/2.x error is an expected one. Those | ||
| * versions have no `kind`, and what counts as expected differs between server and client. | ||
| */ | ||
| export function shouldCaptureError(input: SentryHandleErrorInput, isExpectedLegacyError: () => boolean): boolean { | ||
| if (input.kind) { | ||
| return shouldCaptureCaughtError(input); | ||
| } | ||
|
|
||
| return !isExpectedLegacyError(); | ||
| } | ||
|
|
||
| /** | ||
| * The SvelteKit 3+ rule. Every error reaches `handleError` there — including expected ones thrown | ||
| * with `error(...)` and framework errors like 404s, neither of which showed up here on SvelteKit 2. | ||
| * We apply the same rule the rest of the SDK uses for thrown `HttpError`s (see `sendErrorToSentry`): | ||
| * 4xx are expected and noisy, 5xx are worth reporting. | ||
| */ | ||
| function shouldCaptureCaughtError(input: CaughtErrorInput): boolean { | ||
| // Invalid remote function arguments are a caller mistake, not an app failure. SvelteKit always | ||
| // gives these a 400, but don't let that be the only reason we skip them. | ||
| if (input.kind === 'validation') { | ||
| return false; | ||
| } | ||
|
|
||
| // Unexpected errors have no status of their own; SvelteKit reports them as 500s. | ||
| if (input.kind === 'unknown') { | ||
| return true; | ||
| } | ||
|
|
||
| const status = getErrorStatus(input.error); | ||
|
|
||
| // If we can't tell, err on the side of capturing. | ||
| return status === undefined || status >= 500; | ||
| } | ||
|
sentry[bot] marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.