diff --git a/.changeset/plenty-radios-turn.md b/.changeset/plenty-radios-turn.md new file mode 100644 index 000000000000..3601a1386c49 --- /dev/null +++ b/.changeset/plenty-radios-turn.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +Reset stack traces to avoid double-fix diff --git a/packages/kit/src/runtime/server/page/render.js b/packages/kit/src/runtime/server/page/render.js index fb6bc1bb4eac..d8d5741263ef 100644 --- a/packages/kit/src/runtime/server/page/render.js +++ b/packages/kit/src/runtime/server/page/render.js @@ -72,7 +72,9 @@ export async function render_response({ /** @type {import('types').NormalizedLoadOutputCache | undefined} */ let cache; - if (error) { + const stack = error?.stack; + + if (options.dev && error) { error.stack = options.get_stack(error); } @@ -315,6 +317,11 @@ export async function render_response({ } } + if (options.dev && error) { + // reset stack, otherwise it may be 'fixed' a second time + error.stack = stack; + } + return new Response(html, { status, headers diff --git a/packages/kit/src/vite/dev/index.js b/packages/kit/src/vite/dev/index.js index b118afc23070..c042c0f16f42 100644 --- a/packages/kit/src/vite/dev/index.js +++ b/packages/kit/src/vite/dev/index.js @@ -302,9 +302,7 @@ export async function dev(vite, vite_config, svelte_config) { { csp: svelte_config.kit.csp, dev: true, - get_stack: (error) => { - return fix_stack_trace(error); - }, + get_stack: (error) => fix_stack_trace(error), handle_error: (error, event) => { hooks.handleError({ error: new Proxy(error, { @@ -375,9 +373,8 @@ export async function dev(vite, vite_config, svelte_config) { } } catch (e) { const error = coalesce_to_error(e); - vite.ssrFixStacktrace(error); res.statusCode = 500; - res.end(error.stack); + res.end(fix_stack_trace(error)); } }); }; diff --git a/packages/kit/test/apps/basics/src/routes/errors/stack-trace/_bad.js b/packages/kit/test/apps/basics/src/routes/errors/stack-trace/_bad.js new file mode 100644 index 000000000000..b8ab69cae788 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/errors/stack-trace/_bad.js @@ -0,0 +1,6 @@ +const bad = foo().toUpperCase(); +export default bad; + +// @ts-expect-error +/** @returns {string} */ +function foo() {} diff --git a/packages/kit/test/apps/basics/src/routes/errors/stack-trace/index.svelte b/packages/kit/test/apps/basics/src/routes/errors/stack-trace/index.svelte new file mode 100644 index 000000000000..c186e7e4d227 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/errors/stack-trace/index.svelte @@ -0,0 +1,5 @@ + + +

{bad}

diff --git a/packages/kit/test/apps/basics/test/server.test.js b/packages/kit/test/apps/basics/test/server.test.js index 2e1f27f74dbc..a964b1e308a5 100644 --- a/packages/kit/test/apps/basics/test/server.test.js +++ b/packages/kit/test/apps/basics/test/server.test.js @@ -380,6 +380,19 @@ test.describe('Errors', () => { expect(/** @type {Response} */ (response).status()).toBe(400); } }); + + test('stack traces are not fixed twice', async ({ page }) => { + await page.goto('/errors/stack-trace'); + expect(await page.textContent('#message')).toBe( + 'This is your custom error page saying: "Cannot read properties of undefined (reading \'toUpperCase\')"' + ); + + // check the stack wasn't mutated + await page.goto('/errors/stack-trace'); + expect(await page.textContent('#message')).toBe( + 'This is your custom error page saying: "Cannot read properties of undefined (reading \'toUpperCase\')"' + ); + }); }); test.describe('Load', () => {