Skip to content

fix(react-router): skip manifest patch caching on aborted route discovery - #15359

Open
kdelay wants to merge 1 commit into
remix-run:mainfrom
kdelay:kdelay/fix-fog-of-war-abort-poisoning
Open

fix(react-router): skip manifest patch caching on aborted route discovery#15359
kdelay wants to merge 1 commit into
remix-run:mainfrom
kdelay:kdelay/fix-fog-of-war-abort-poisoning

Conversation

@kdelay

@kdelay kdelay commented Jul 31, 2026

Copy link
Copy Markdown

fetchAndApplyManifestPatches mutates manifest.routes and adds the requested paths to the module-level discoveredPaths cache as soon as the manifest response settles, but the patch callback the router hands to patchRoutesOnNavigation no-ops once the triggering navigation/fetcher signal has aborted (router.ts).

If an abort lands in the window between the manifest JSON settling and the patches being applied, the paths end up cached as discovered while the client route tree was never patched. Every later navigation to those paths early-returns at the discoveredPaths check, so discovery never runs again for the rest of the session — a splat route can match instead and its server loader runs, or a later child patch fails with No route found to patch children into. Only a hard reload clears it, since the cache is module state.

This bails out before either mutation when the signal has aborted, so an aborted discovery leaves no trace and the next navigation to that path discovers it normally. The eager prefetch path in useFogOFWarDiscovery passes no signal, so it is unaffected.

Closes #15327

Tests

packages/react-router/__tests__/dom/ssr/fog-of-war-test.ts now drives getPatchRoutesOnNavigationFunction with a mocked fetch (as lazy-discovery-test.ts does) and a patch that mirrors the router's abort no-op:

  • a discovery aborted while the manifest is being read is re-attempted and patched on the next navigation to the same path — this failed before the change, because the second attempt never re-fetched
  • a discovery that is not aborted still patches once and is not fetched again

…very

fetchAndApplyManifestPatches mutated manifest.routes and added the paths to the
discoveredPaths cache as soon as the manifest response settled, but the router's
patch callback no-ops once the triggering navigation/fetcher signal has aborted.
An abort landing in that window left the paths cached as discovered with the
route tree never patched, so every later navigation to those paths early-returned
from discovery for the rest of the session.

Bail out before both mutations when the signal has aborted.
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

⚠️ CLA Signature Required

Hi @kdelay, thanks for contributing to React Router!

Before we consider your pull request, we ask that you sign our Contributor License Agreement (CLA). We require this only once.

You may review the CLA and sign it by adding your GitHub username to contributors.yml.

Once the CLA is signed, the CLA Signed label will be added to the pull request and the CI check will pass.

Thanks!

- The Remix team

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

✅ Change File Found

One or more change files found.

Type Change
patch Don't cache a lazily-discovered path when the navigation/fetcher that triggered discovery aborts mid-flight

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Aborted navigation during route discovery permanently poisons discoveredPaths — path cached as discovered, route tree never patched

2 participants