Skip to content

router.navigate hangs after RouterProvider unmount in tests (regression in ^1.170.19) #8125

Description

@Sachinvs23

Which project does this relate to?

Router

Describe the bug

After upgrading from @tanstack/react-router@1.170.18 to @tanstack/react-router@1.170.19 and above, calls to router.navigate(...) can hang (the returned promise never resolves) in test environments when:

  • A shared router instance has had a RouterProvider mounted at least once, and
  • That RouterProvider has been unmounted (test cleanup), and
  • A later test calls await router.navigate(...) while no RouterProvider is mounted.

On 1.170.18 the same test setup passes; on 1.170.19 the navigation promise never resolves and the test times out.

This is happening in a browser test setup (Vitest + Playwright + Chromium) where we:

  • Create a single router instance via createRouter(...),
  • Mount <RouterProvider router={router} /> in tests,
  • Unmount via Testing Library/Vitest cleanup() after each test,
  • Reuse the same router instance across tests.

Once a RouterProvider has been mounted and torn down, subsequent await router.navigate(...) calls when no provider is mounted hang on 1.170.19.

Complete minimal reproducer

https://github.com/Sachinvs23/React-router-navigate-hang

Steps to Reproduce the Bug

  1. Clone the reproducer repo:

    git clone https://github.com/Sachinvs23/React-router-navigate-hang
    cd React-router-navigate-hang
    npm install
    
  2. Ensure @tanstack/react-router is pinned to 1.170.19 in package.json.

  3. Run the repro test:

    npm test -- src/router-regression.test.tsx
    
  4. Observe:
    Test “primes RouterProvider once” passes.
    Test “navigates without provider after it was primed” hangs and times out (e.g. after 60s).

  5. Change the router version to 1.170.18:
    "@tanstack/react-router": "1.170.18",

    Reinstall and re-run the same test file:

    npm install
    npm test -- src/router-regression.test.tsx
    
  6. Observe:

    Both tests now pass; await router.navigate(...) resolves even when no RouterProvider is mounted.

Expected behavior


Expected behavior

I expected `router.navigate(...)` to:

- Resolve (or reject) promptly, even when no `RouterProvider` is currently mounted, **or**
- At least behave consistently between `1.170.18` and `1.170.19`.

In particular:

- With a shared router instance that has previously had a `RouterProvider` mounted and then unmounted,
- Calling `await router.navigate({ to: '/foo' })` while no provider is mounted should not hang forever.


### Screenshots or Videos

_No response_

### Platform

- TanStack Router:
  - @tanstack/react-router: 1.170.18 (works), 1.170.19 (hangs)
- React: 19.2.8
- Node: 24.13.1
- Bundler: Vite 8.2.1
- Test runner: Vitest 4.1.10 (browser mode with Playwright provider)
- Browser: Chromium (via Playwright in Vitest)
- OS: Windows 11


### Additional context

Additional observations:

- The router instance is shared across tests (`createRouter(...)` called once and exported).
- We mount `<RouterProvider router={router} />` in tests and unmount via Testing Library/Vitest `cleanup()` after each test.
- On 1.170.19, if we call `await router.navigate(...)` **before mounting a new RouterProvider** in a later test, the navigation promise never resolves.
- We instrumented the router with `router.subscribe('onBeforeNavigate'|'onLoad'|'onResolved'|'onRendered')` and wrapping `router.navigate`.
  - In the hanging case, we see `navigate start` and `onBeforeNavigate`, but `onLoad`, `onResolved`, and `navigate end` never fire.

Workarounds:

- If we always mount `<RouterProvider router={router} />` **before** awaiting `router.navigate(...)` in tests, the hang goes away.
- If we use a **fresh router per test** (calling `createRouter(...)` in `beforeEach` and passing it to `RouterProvider`), the hang also disappears.

Impact:

- This is a behavioral change between 1.170.18 and 1.170.19 and affects test setups that reuse a router instance and sometimes call `navigate` while the adapter is not currently mounted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions