diff --git a/.changeset/shaggy-ghosts-decide.md b/.changeset/shaggy-ghosts-decide.md new file mode 100644 index 000000000000..b7cb1243ecdc --- /dev/null +++ b/.changeset/shaggy-ghosts-decide.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: fail prerendering when remote function fails diff --git a/packages/kit/src/runtime/server/remote.js b/packages/kit/src/runtime/server/remote.js index d2cd2f192d18..e4d199dc3f27 100644 --- a/packages/kit/src/runtime/server/remote.js +++ b/packages/kit/src/runtime/server/remote.js @@ -176,13 +176,19 @@ async function handle_remote_call_internal(event, state, options, manifest, id) }); } + const status = + error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500; + return json( /** @type {RemoteFunctionResponse} */ ({ type: 'error', error: await handle_error_and_jsonify(event, state, options, error), - status: error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500 + status }), { + // By setting a non-200 during prerendering we fail the prerender process (unless handleHttpError handles it). + // Errors at runtime will be passed to the client and are handled there + status: state.prerendering ? status : undefined, headers: { 'cache-control': 'private, no-store' } diff --git a/packages/kit/test/build-errors/apps/prerender-remote-function-error/package.json b/packages/kit/test/build-errors/apps/prerender-remote-function-error/package.json new file mode 100644 index 000000000000..cf1d0aa90198 --- /dev/null +++ b/packages/kit/test/build-errors/apps/prerender-remote-function-error/package.json @@ -0,0 +1,22 @@ +{ + "name": "prerenderable-remote-function-error", + "private": true, + "version": "0.0.1", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "prepare": "svelte-kit sync", + "check": "svelte-kit sync && tsc && svelte-check" + }, + "devDependencies": { + "@sveltejs/adapter-auto": "workspace:^", + "@sveltejs/kit": "workspace:^", + "@sveltejs/vite-plugin-svelte": "catalog:", + "svelte": "^5.38.5", + "svelte-check": "^4.1.1", + "typescript": "^5.5.4", + "vite": "catalog:" + }, + "type": "module" +} diff --git a/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/app.html b/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/app.html new file mode 100644 index 000000000000..866ddd01e176 --- /dev/null +++ b/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/routes/+layout.js b/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/routes/+layout.js new file mode 100644 index 000000000000..189f71e2e1b3 --- /dev/null +++ b/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/routes/+layout.js @@ -0,0 +1 @@ +export const prerender = true; diff --git a/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/routes/+page.svelte b/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/routes/+page.svelte new file mode 100644 index 000000000000..25e7015aefb5 --- /dev/null +++ b/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/routes/+page.svelte @@ -0,0 +1,7 @@ + + +{#await throws() then value} + {value} +{/await} diff --git a/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/routes/data.remote.ts b/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/routes/data.remote.ts new file mode 100644 index 000000000000..23270e9ac3d7 --- /dev/null +++ b/packages/kit/test/build-errors/apps/prerender-remote-function-error/src/routes/data.remote.ts @@ -0,0 +1,5 @@ +import { prerender } from '$app/server'; + +export const throws = prerender(() => { + throw new Error('remote function blew up'); +}); diff --git a/packages/kit/test/build-errors/apps/prerender-remote-function-error/static/favicon.png b/packages/kit/test/build-errors/apps/prerender-remote-function-error/static/favicon.png new file mode 100644 index 000000000000..825b9e65af7c Binary files /dev/null and b/packages/kit/test/build-errors/apps/prerender-remote-function-error/static/favicon.png differ diff --git a/packages/kit/test/build-errors/apps/prerender-remote-function-error/svelte.config.js b/packages/kit/test/build-errors/apps/prerender-remote-function-error/svelte.config.js new file mode 100644 index 000000000000..f9e8b0b2b482 --- /dev/null +++ b/packages/kit/test/build-errors/apps/prerender-remote-function-error/svelte.config.js @@ -0,0 +1,14 @@ +import adapter from '../../../../../adapter-auto/index.js'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + kit: { + adapter: adapter(), + + experimental: { + remoteFunctions: true + } + } +}; + +export default config; diff --git a/packages/kit/test/build-errors/apps/prerender-remote-function-error/tsconfig.json b/packages/kit/test/build-errors/apps/prerender-remote-function-error/tsconfig.json new file mode 100644 index 000000000000..b1096bf168cd --- /dev/null +++ b/packages/kit/test/build-errors/apps/prerender-remote-function-error/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "noEmit": true + }, + "extends": "./.svelte-kit/tsconfig.json" +} diff --git a/packages/kit/test/build-errors/apps/prerender-remote-function-error/vite.config.js b/packages/kit/test/build-errors/apps/prerender-remote-function-error/vite.config.js new file mode 100644 index 000000000000..3f12d3677ea6 --- /dev/null +++ b/packages/kit/test/build-errors/apps/prerender-remote-function-error/vite.config.js @@ -0,0 +1,23 @@ +import * as path from 'node:path'; +import { sveltekit } from '@sveltejs/kit/vite'; + +/** @type {import('vite').UserConfig} */ +const config = { + build: { + minify: false + }, + + clearScreen: false, + + logLevel: 'silent', + + plugins: [sveltekit()], + + server: { + fs: { + allow: [path.resolve('../../../../src')] + } + } +}; + +export default config; diff --git a/packages/kit/test/build-errors/prerender.spec.js b/packages/kit/test/build-errors/prerender.spec.js index 0bda6a070781..903d2491e858 100644 --- a/packages/kit/test/build-errors/prerender.spec.js +++ b/packages/kit/test/build-errors/prerender.spec.js @@ -29,3 +29,15 @@ test('entry generators should match their own route', { timeout }, () => { `Error: The entries export from /[slug]/[notSpecific] generated entry /whatever/specific, which was matched by /[slug]/specific - see the \`handleEntryGeneratorMismatch\` option in https://svelte.dev/docs/kit/configuration#prerender for more info.${EOL}To suppress or handle this error, implement \`handleEntryGeneratorMismatch\` in https://svelte.dev/docs/kit/configuration#prerender` ); }); + +test('an error in a `prerender` function should fail the build', { timeout }, () => { + assert.throws( + () => + execSync('pnpm build', { + cwd: path.join(process.cwd(), 'apps/prerender-remote-function-error'), + stdio: 'pipe', + timeout + }), + /remote function blew up/ + ); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a97c77ecc4bb..7741f57fcb27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -816,6 +816,30 @@ importers: specifier: 'catalog:' version: 6.3.6(@types/node@18.19.119)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + packages/kit/test/build-errors/apps/prerender-remote-function-error: + devDependencies: + '@sveltejs/adapter-auto': + specifier: workspace:^ + version: link:../../../../../adapter-auto + '@sveltejs/kit': + specifier: workspace:^ + version: link:../../../.. + '@sveltejs/vite-plugin-svelte': + specifier: 'catalog:' + version: 6.0.0-next.3(svelte@5.38.5)(vite@6.3.6(@types/node@18.19.119)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + svelte: + specifier: ^5.38.5 + version: 5.38.5 + svelte-check: + specifier: ^4.1.1 + version: 4.1.1(picomatch@4.0.3)(svelte@5.38.5)(typescript@5.8.3) + typescript: + specifier: ^5.5.4 + version: 5.8.3 + vite: + specifier: 'catalog:' + version: 6.3.6(@types/node@18.19.119)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + packages/kit/test/build-errors/apps/prerenderable-incorrect-fragment: devDependencies: '@sveltejs/adapter-auto':