sveltejs / sveltejs/kit

trailingSlash=always ignored on client render when error boundary is defined before/above node config

Open
#13,516 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

error handling router
Dominant language
JavaScript
Stars
20.8k
Forks
2.3k
Avg merge
1d 16h
Merged PRs (30d)
156

Description

Describe the bug

Issue

I'm a bit newer to svelte kit, so it's a bit unclear if this is actually intended behavior, but I couldn't find any documentation around it, and the behavior feels like a bug.

Given a file structure like:

routes/
  test/
    +page.js // trailingSlash = 'always' configured here
    +page.svelte
  // important: no trailingSlash = 'always' is set at a higher level

If an http error (error()) is thrown in the loader for /test/, the client render/hydration will change the url.pathname to /test without the trailing slash. In our specific app, it actually caused an infinite redirect because of how we ensure trailing slash; however, for svelte kit, but you can still replicate in a brand new svelte kit app that it changes the url incorrectly, but doesn't seem to cause an infinite redirect.

This behavior only happens during client loading (via CSN to the page that errors) or client hydration after server render.

Example

Locally:
Image

Stack Blitz:

Image

Cause

https://github.com/sveltejs/kit/blob/3cf2b77b4ae87bbd4fc46367c37c129133af41f1/packages/kit/src/runtime/client/client.js#L1058-L1068

On this specific line:

branch: branch.slice(0, error_load.idx).concat(error_load.node),

Given a branch structure like:

layout
  layout (error.svelte could be defined at this layer or above or not at all)
    page (trailingSlash defined here)

The branch value passed into get_navigation_result_from_branch will remove all nodes below the error node which removes the trailing slash config and the url.pathname will get overridden to the default never setting: https://github.com/sveltejs/kit/blob/3cf2b77b4ae87bbd4fc46367c37c129133af41f1/packages/kit/src/runtime/client/client.js#L503-L515

Work around

To prevent this issue from happening, you need to just ensure that the closest error.svelte to the route is below where the trailingSlash = 'always' config is set.

So defining trailingSlash = 'always' in a root layout could fix the issue (if no error.svelte is configured in the app), or just actually defining an error.svelte in folder below where the trailingSlash is configured (and obviously above or at where the actual route loader is).

Reproduction

StackBlitz

Logs

System Info
System:
    OS: macOS 15.3.1
    CPU: (12) arm64 Apple M3 Pro
    Memory: 120.05 MB / 36.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.20.6 - ~/bin/node
    npm: 10.8.2 - ~/bin/npm
  Browsers:
    Chrome: 133.0.6943.142
    Safari: 18.3
  npmPackages:
    @sveltejs/adapter-auto: ^4.0.0 => 4.0.0 
    @sveltejs/kit: ^2.16.0 => 2.17.3 
    @sveltejs/vite-plugin-svelte: ^5.0.0 => 5.0.3 
    svelte: ^5.0.0 => 5.20.5 
    vite: ^6.0.0 => 6.2.0
Severity

annoyance

Additional Information

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the StackBlitz reproduction and inspect packages/kit/src/runtime/client/client.js around lines 1058-1068 and 503-515. Trace how the truncated branch affects trailingSlash during client navigation and hydration when the error boundary is above the route configuration. Done means preserving the configured trailing slash for the error page without breaking normal error handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
56/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.