diff --git a/packages/sveltekit/src/client/load.ts b/packages/sveltekit/src/client/load.ts index 14528959d34e..3e454bdb364a 100644 --- a/packages/sveltekit/src/client/load.ts +++ b/packages/sveltekit/src/client/load.ts @@ -4,7 +4,7 @@ import { addNonEnumerableProperty, objectify } from '@sentry/utils'; import type { LoadEvent } from '@sveltejs/kit'; import type { SentryWrappedFlag } from '../common/utils'; -import { isRedirect } from '../common/utils'; +import { isHttpError, isRedirect } from '../common/utils'; type PatchedLoadEvent = LoadEvent & Partial; @@ -14,7 +14,11 @@ function sendErrorToSentry(e: unknown): unknown { const objectifiedErr = objectify(e); // We don't want to capture thrown `Redirect`s as these are not errors but expected behaviour - if (isRedirect(objectifiedErr)) { + // Neither 4xx errors, given that they are not valuable. + if ( + isRedirect(objectifiedErr) || + (isHttpError(objectifiedErr) && objectifiedErr.status < 500 && objectifiedErr.status >= 400) + ) { return objectifiedErr; } diff --git a/packages/sveltekit/test/client/load.test.ts b/packages/sveltekit/test/client/load.test.ts index e839b5a9cba5..ca7c1d625224 100644 --- a/packages/sveltekit/test/client/load.test.ts +++ b/packages/sveltekit/test/client/load.test.ts @@ -69,6 +69,30 @@ describe('wrapLoadWithSentry', () => { expect(mockCaptureException).not.toHaveBeenCalled(); }); + it.each([400, 404, 499])("doesn't call captureException for thrown `HttpError`s with status %s", async status => { + async function load(_: Parameters[0]): Promise> { + throw { status, body: 'error' }; + } + + const wrappedLoad = wrapLoadWithSentry(load); + const res = wrappedLoad(MOCK_LOAD_ARGS); + await expect(res).rejects.toThrow(); + + expect(mockCaptureException).not.toHaveBeenCalled(); + }); + + it.each([500, 501, 599])('calls captureException for thrown `HttpError`s with status %s', async status => { + async function load(_: Parameters[0]): Promise> { + throw { status, body: 'error' }; + } + + const wrappedLoad = wrapLoadWithSentry(load); + const res = wrappedLoad(MOCK_LOAD_ARGS); + await expect(res).rejects.toThrow(); + + expect(mockCaptureException).toHaveBeenCalledTimes(1); + }); + describe('calls trace function', async () => { it('creates a load span', async () => { async function load({ params }: Parameters[0]): Promise> {