Skip to content

About

reproduce tanstack router redirect race condition

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

The error happens deterministicaly on the first try with @tanstack/react-router@^1.170.16 and @tanstack/react-start@^1.168.26.

Running the repro

The crash reproduces against the production build, so build the app and start the built server (not pnpm dev) before running the repro loop:

# 1. build the production server
pnpm build

# 2. start the built server (serves on http://localhost:3000)
node .output/server/index.mjs

# 3. in another terminal, run the repro loop against it
BASE_URL="http://localhost:3000" TARGET_PATH="/home?searchParam=true" pnpm tsx scripts/repro-home-crash.ts

Testing against a local build of TanStack Router

The published npm packages are built artifacts (dist/), while a git checkout only contains source (src/). To reproduce/fix against your own changes you must build the router packages and consume the built output, not raw source — otherwise behavior diverges (dev-vs-prod builds, missing Start code transforms) and the crash may not reproduce.

This repo expects the router monorepo checked out as a sibling directory:

tanstack-router-fix/
├── redirect-race-app/   # this repo
├── tanstack/router/     # your fork/clone of tanstack/router
└── local-tgz/           # generated tarballs (created by the steps below)

The fix here only touches @tanstack/react-router and @tanstack/router-core, so only those two packages need to be built and overridden. pnpm overrides are global, so @tanstack/react-start (kept from npm) transitively resolves to the local build too.

One-time setup: point this app at the local build

pnpm v10+ reads overrides from pnpm-workspace.yaml (not package.json). This app's pnpm-workspace.yaml already contains:

overrides:
  '@tanstack/react-router': file:../local-tgz/tanstack-react-router-1.170.17.tgz
  '@tanstack/router-core': file:../local-tgz/tanstack-router-core-1.171.14.tgz

Keep those filenames in sync with the versions in the router monorepo's packages/*/package.json — if a version bumps, update the filenames to match.

Rebuild after every router source change

Run this entire block from the redirect-race-app directory. It is chained with &&, so if any step fails the rest stops — you can't accidentally pack a stale dist/ (the #1 gotcha: the build must run before the pack). Paste it as one unit; don't cherry-pick lines.

# --- from redirect-race-app/ ---
( cd ../tanstack/router \
  && TGZ="$(cd ../.. && pwd)/local-tgz" && mkdir -p "$TGZ" \
  && pnpm --filter @tanstack/router-core  build \
  && pnpm --filter @tanstack/react-router build \
  && pnpm --filter @tanstack/router-core  exec pnpm pack --pack-destination "$TGZ" \
  && pnpm --filter @tanstack/react-router exec pnpm pack --pack-destination "$TGZ" ) \
&& pnpm install --force --update-checksums \
&& rm -rf .output \
&& pnpm build

What each part does, and why it's needed:

  • Build router-core first, then react-router, each via its own vite build. router-core is built first because react-router depends on it. Don't use pnpm build / nx at the repo root — nx needs a platform-native binary that's often missing in a fresh/cross-arch install.
  • Pack to an absolute $TGZ. pnpm --filter <pkg> exec runs in the package directory, so a relative --pack-destination ../../local-tgz would write to tanstack/router/local-tgz — the wrong place — and this app would silently keep installing a stale tarball. $TGZ resolves the correct absolute path (matching the overrides). Tarballs are what npm actually publishes, so peer deps (react, react-dom) resolve to this app's single copy — no dual-React / duplicate-instance footguns that pnpm link causes.
  • pnpm install --force — required. The tarball filenames/versions are unchanged, so a plain pnpm install sees the lockfile as satisfied and keeps the old content; --force re-extracts.
  • rm -rf .output && pnpm build — rebuild the production server, which bundles react-router into .output/server/index.mjs. Skipping this (or not restarting the server) means the running server still has the old code.

Then start the freshly built server:

node .output/server/index.mjs

Reverting to npm

Remove the overrides: block from pnpm-workspace.yaml and run pnpm install.

About

reproduce tanstack router redirect race condition

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages