Skip to content

fix: correctly serve ISR pages with trailing slash set to 'always' - #16903

Merged
Rich-Harris merged 12 commits into
version-3from
teemingc-vercel-isr-trailing-slash-test
Aug 27, 2026
Merged

fix: correctly serve ISR pages with trailing slash set to 'always'#16903
Rich-Harris merged 12 commits into
version-3from
teemingc-vercel-isr-trailing-slash-test

Conversation

@teemingc

@teemingc teemingc commented Aug 22, 2026

Copy link
Copy Markdown
Member

Fixed #12556


Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

Edits

  • Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.

Adds a route with ISR enabled and trailingSlash set to "always" along
with a platform test that navigates to it and verifies the URL pathname
stays correct, the page renders, and no network or console errors occur.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@pkg-svelte-dev

pkg-svelte-dev Bot commented Aug 22, 2026

Copy link
Copy Markdown

Install the latest version of @sveltejs/kit from 8ab1c3e:

pnpm add https://pkg.svelte.dev/@sveltejs/kit/c/8ab1c3eafee04b2d06867377a7805e828e4754e0

Open in pkg.svelte.dev: https://pkg.svelte.dev/repos/kit/pr/16903

@changeset-bot

changeset-bot Bot commented Aug 22, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c507758

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@teemingc
teemingc marked this pull request as draft August 22, 2026 12:42
@teemingc teemingc added the pkg:adapter-vercel Pertaining to the Vercel adapter label Aug 22, 2026
@teemingc teemingc changed the title test(adapter-vercel): add ISR + trailingSlash always platform test fix: ensure ISR pages with trailing slash configured loads correctly Aug 22, 2026
@teemingc teemingc added the needs-platform-tests This PR needs to run platform tests in order to merge. label Aug 22, 2026
@svelte-docs-bot

Copy link
Copy Markdown

…vent redirect loops

When ISR is enabled on a page with trailingSlash: 'always', the __pathname
query param didn't include the trailing slash, causing SvelteKit to issue
a redirect. Since ISR rewrites route back through the same handler, this
created an infinite loop (visible as doubled path segments in the URL).

Fix: detect when the Vercel route pattern has a trailing /? optional slash,
convert it to a capture group (/)?, and use the corresponding
backreference in __pathname so the slash is preserved when present.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@teemingc
teemingc had a problem deploying to @sveltejs/adapter-vercel platform tests August 22, 2026 16:07 — with GitHub Actions Failure
@teemingc
teemingc temporarily deployed to @sveltejs/adapter-vercel platform tests August 22, 2026 16:07 — with GitHub Actions Inactive
teemingc and others added 6 commits August 23, 2026 00:24
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@teemingc
teemingc force-pushed the teemingc-vercel-isr-trailing-slash-test branch from dc0723d to 85770ef Compare August 22, 2026 17:09
@teemingc
teemingc marked this pull request as ready for review August 22, 2026 17:24
Comment thread packages/adapter-vercel/test/apps/basic/test/test.ts Outdated
Co-authored-by: Nic Polumeyv <nicolas.polum@outlook.com>
@teemingc teemingc changed the title fix: ensure ISR pages with trailing slash configured loads correctly chore: add failing test for ISR pages with trailing slash set to 'always' Aug 24, 2026
Comment thread .github/workflows/platform-tests-vercel.yml Outdated
teemingc and others added 2 commits August 24, 2026 17:03
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
@teemingc teemingc changed the title chore: add failing test for ISR pages with trailing slash set to 'always' fix: correctly serve ISR pages with trailing slash set to 'always' Aug 25, 2026
@teemingc

Copy link
Copy Markdown
Member Author

@Nic-Polumeyv can you explain how the fix works? What happens to ISR routes with dynamic segments? Are they disallowed now or do they just still work?

@Nic-Polumeyv

Copy link
Copy Markdown
Contributor

No problem, took me a couple hours to figure out!

Vercel resolves a request in three steps (first match wins):

1. routes listed before `handle: filesystem`
2. filesystem: a file or function at exactly this path? (/foo and /foo/ both count)
3. routes listed after `handle: filesystem`

adapter-vercel put every ISR src route in step 3. Only a src route attaches __pathname; a filesystem hit passes nothing, so the function only ever sees its own file path.

/isr/[slug] never gets caught by step 2. Its function is the file isr/[slug].func and no request has that path, so it falls through to step 3 and the src route captures the URL. /isr-trailing-slash does get caught by step 2, because its function is the file isr-trailing-slash.func, which is its URL:

GET /isr-trailing-slash/
  step 2: isr-trailing-slash.func exists → run it, no __pathname
  function sees its own path: /isr-trailing-slash (slash lost)
  kit: trailingSlash 'always', no slash → 308 to /isr-trailing-slash/
GET /isr-trailing-slash/
  same again

The (/)?, %2F and (/?) commits changed the src regex for /isr-trailing-slash in config.json. That regex is in step 3. Vercel never ran it, because step 2 had already served the request.

The fix puts ISR routes with no dynamic segments in step 1. Dynamic ones stay in step 3, since a [...rest] ISR route in step 1 would swallow every static asset.

Separately, dest no longer rebuilds the pathname from route segments. The src regex is wrapped in one capture group and dest is ?__pathname=$1, so the function gets the path as requested. That is what deletes get_pathname and the // cleanup in the wrapper.

Dynamic ISR routes still work, nothing about their placement changed. The one difference is /isr/alpha/ now 308s to /isr/alpha instead of being served, same as the other adapters.

@Rich-Harris Rich-Harris left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

brilliant!

@Rich-Harris
Rich-Harris merged commit d5863ab into version-3 Aug 27, 2026
72 of 73 checks passed
@Rich-Harris
Rich-Harris deleted the teemingc-vercel-isr-trailing-slash-test branch August 27, 2026 21:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-platform-tests This PR needs to run platform tests in order to merge. pkg:adapter-vercel Pertaining to the Vercel adapter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vercel Adapter — Trailing slash option causes redirect loop

3 participants