Skip to content

fix: re-evaluate preloaded redirects before navigation - #16930

Closed
bmdavis419 wants to merge 1 commit into
sveltejs:version-3from
bmdavis419:fix/preloaded-redirect-cache
Closed

fix: re-evaluate preloaded redirects before navigation#16930
bmdavis419 wants to merge 1 commit into
sveltejs:version-3from
bmdavis419:fix/preloaded-redirect-cache

Conversation

@bmdavis419

Copy link
Copy Markdown
Contributor

Prevent stale preloaded redirects from causing incorrect navigation and redirect loops.

  • Reevaluate cached redirect decisions without changing successful preload caching.
  • Cover state changes before navigation and during redirect chains.
  • Verified with 750 unit tests, 100 browser tests, production builds, server-side routing, lint, and monorepo checks.

Important files:

  • packages/kit/src/runtime/client/client.js
    • Discard only the matching cached redirect and reload its route against current state.
  • packages/kit/test/apps/basics/test/cross-platform/client.test.js
    • Add browser regressions for stale redirect decisions and redirect-induced state changes.
  • packages/kit/test/apps/basics/src/routes/routing/preloading/redirect/[step]/+page.server.js
    • Add a cookie-isolated redirect fixture used by both regression tests.

Before and after:

Before: stale redirect causes a 500 error After: redirect is reevaluated and the dashboard loads
Before: the stale preloaded redirect produces a 500 error After: the fixed redirect successfully loads the dashboard

References #16484.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed an issue where preloaded redirects could be reused after application state changes.
    • Navigation now reevaluates redirects and reaches the updated destination correctly.
  • Tests

    • Added coverage for redirect behavior after cookie changes and redirect-driven state changes.
    • Added a redirect resolution scenario displaying a “Redirect resolved” confirmation.

@pkg-svelte-dev

Copy link
Copy Markdown

Install the latest version of @sveltejs/kit from a089be9:

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

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

Note

This PR is from a fork. A maintainer must approve approve each commit before it can be built and installed.

@changeset-bot

changeset-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a089be9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/kit Patch

Not sure what this means? Click here to learn what changesets are.

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

@teemingc teemingc changed the title BUGFIX: Re-evaluate preloaded redirects before navigation fix: re-evaluate preloaded redirects before navigation Aug 25, 2026
Comment on lines +1419 to +1423
const result = await cache.promise;
if (result.type !== 'redirect') return result;

// Redirects depend on transient state and must be reevaluated when navigating.
if (load_cache === cache) discard_load_cache();

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.

I don't think this is the right fix. See #16484 (comment)

Rich-Harris pushed a commit that referenced this pull request Aug 27, 2026
In `runtime/client/client.js`, `_preload_data` stores every `load_route`
result in `load_cache` and `load_route` hands the entry back whenever
the intent id matches. `navigate` only clears `load_cache` on the commit
path, after `history.pushState`; the redirect branch recurses into
`navigate` for the redirect target and returns before that. So when a
preloaded route redirects and a later hop of the same navigation comes
back to it (a gate: `/dashboard` redirects to `/select` until a flag is
set, `/select` sets it and redirects to `/dashboard`), the cached
redirect is replayed without a fetch on every return until the
20-redirect limit renders the 500 page.

Discard the consumed entry in the redirect branch before recursing,
keyed on `intent.id` so a preload of a different route (such as the
redirect target) survives. The first hop is still served from the
preload; anything after it loads fresh.

Fixes #16484.

Replaces #16930. Thank you for the attempt @bmdavis419, big fan of your
content.

Co-authored-by: Benjamin Davis <davis.benjamin41902@gmail.com>
@Rich-Harris

Copy link
Copy Markdown
Member

closing in favour of #16955

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preloaded redirect results are cached and replayed, causing stale redirects and redirect loops

3 participants