diff --git a/.changeset/fix-trailing-slash-error-boundary.md b/.changeset/fix-trailing-slash-error-boundary.md
new file mode 100644
index 000000000000..1800d9b5b67d
--- /dev/null
+++ b/.changeset/fix-trailing-slash-error-boundary.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: preserve trailing slash when error boundary truncates branch
diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js
index c410814399ee..f7cabc43d70d 100644
--- a/packages/kit/src/runtime/client/client.js
+++ b/packages/kit/src/runtime/client/client.js
@@ -633,7 +633,7 @@ async function initialize(result, target, hydrate) {
*/
function get_navigation_result_from_branch({ url, params, branch, status, error, route, form }) {
/** @type {import('types').TrailingSlash} */
- let slash = 'never';
+ let slash = error ? 'ignore' : 'never';
// if `paths.base === '/a/b/c`, then the root route is always `/a/b/c/`, regardless of
// the `trailingSlash` route option, so that relative paths to JS and CSS work
diff --git a/packages/kit/test/apps/basics/src/routes/routing/trailing-slash/error/+error.svelte b/packages/kit/test/apps/basics/src/routes/routing/trailing-slash/error/+error.svelte
new file mode 100644
index 000000000000..2d004da1677b
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/routing/trailing-slash/error/+error.svelte
@@ -0,0 +1,5 @@
+
+
+
Error: {page.error?.message}
diff --git a/packages/kit/test/apps/basics/src/routes/routing/trailing-slash/error/always-error/+page.js b/packages/kit/test/apps/basics/src/routes/routing/trailing-slash/error/always-error/+page.js
new file mode 100644
index 000000000000..03381a145a6d
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/routing/trailing-slash/error/always-error/+page.js
@@ -0,0 +1,7 @@
+import { error } from '@sveltejs/kit';
+
+export const trailingSlash = 'always';
+
+export function load() {
+ error(500, 'trailing slash error test');
+}
diff --git a/packages/kit/test/apps/basics/src/routes/routing/trailing-slash/error/always-error/+page.svelte b/packages/kit/test/apps/basics/src/routes/routing/trailing-slash/error/always-error/+page.svelte
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/packages/kit/test/apps/basics/test/cross-platform/client.test.js b/packages/kit/test/apps/basics/test/cross-platform/client.test.js
index f47023909969..4a4ec18f8d30 100644
--- a/packages/kit/test/apps/basics/test/cross-platform/client.test.js
+++ b/packages/kit/test/apps/basics/test/cross-platform/client.test.js
@@ -1132,6 +1132,15 @@ test.describe('Routing', () => {
expect(new URL(page.url()).pathname).toBe('/routing/trailing-slash/never');
await expect(page.locator('p')).toHaveText('/routing/trailing-slash/never');
});
+
+ test('trailing slash is preserved when error boundary truncates branch', async ({
+ page,
+ app
+ }) => {
+ await page.goto('/routing/trailing-slash');
+ await app.goto('/routing/trailing-slash/error/always-error/');
+ expect(new URL(page.url()).pathname).toBe('/routing/trailing-slash/error/always-error/');
+ });
});
test.describe('Shadow DOM', () => {