Skip to content

fix(router-core): lane match loader rewrite#7805

Open
Sheraff wants to merge 62 commits into
mainfrom
fix-router-core-lane-match-loader
Open

fix(router-core): lane match loader rewrite#7805
Sheraff wants to merge 62 commits into
mainfrom
fix-router-core-lane-match-loader

Conversation

@Sheraff

@Sheraff Sheraff commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

fixed by this PR

fixes #2980, fixes #3179, fixes #3920, fixes #3928, fixes #4444, fixes #4467, fixes #4476, fixes #4572, fixes #4614, fixes #4759, fixes #5427, fixes #6107, fixes #6221, fixes #6351, fixes #6371, fixes #7051, fixes #7120, fixes #7283, fixes #7367, fixes #7379, fixes #7457, fixes #7602, fixes #7635, fixes #7673, fixes #7753, fixes #7759, fixes #7815

Already fixed on main (but we added tests)

Ignored by this PR

Summary by CodeRabbit

  • New Features

    • Added a selective SSR route demonstrating non-SSR pending timing, plus regression coverage for hydration behavior in DEV mode.
    • Improved router loading to provide more consistent pending/min-pending, retry, and refresh behavior.
  • Bug Fixes

    • Fixed pending fallback behavior across replacements, rapid navigations, and forced-pending invalidations.
    • Server responses now return accurate HTTP status codes for render, redirect, error, and not-found outcomes.
    • Improved resilience when navigation/listeners or loader callbacks throw.
  • Tests

    • Added/expanded e2e and regression tests covering redirects, hydration boundaries, and lazy chunk failures.
  • Documentation / Compatibility

    • Updated preloading and router API/type docs; note removed or renamed router fields/methods.

@nx-cloud

nx-cloud Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 2d639e1

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 10m 55s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 2m 9s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-23 22:29:50 UTC

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

4 package(s) bumped directly, 19 bumped as dependents.

🟩 Patch bumps

Package Version Reason
@tanstack/react-router 1.170.18 → 1.170.19 Changeset
@tanstack/router-core 1.171.15 → 1.171.16 Changeset
@tanstack/solid-router 1.170.18 → 1.170.19 Changeset
@tanstack/vue-router 1.170.17 → 1.170.18 Changeset
@tanstack/react-start 1.168.32 → 1.168.33 Dependent
@tanstack/react-start-client 1.168.16 → 1.168.17 Dependent
@tanstack/react-start-rsc 0.1.31 → 0.1.32 Dependent
@tanstack/react-start-server 1.167.22 → 1.167.23 Dependent
@tanstack/router-cli 1.167.21 → 1.167.22 Dependent
@tanstack/router-generator 1.167.21 → 1.167.22 Dependent
@tanstack/router-plugin 1.168.23 → 1.168.24 Dependent
@tanstack/router-vite-plugin 1.167.23 → 1.167.24 Dependent
@tanstack/solid-start 1.168.32 → 1.168.33 Dependent
@tanstack/solid-start-client 1.168.16 → 1.168.17 Dependent
@tanstack/solid-start-server 1.167.22 → 1.167.23 Dependent
@tanstack/start-client-core 1.170.14 → 1.170.15 Dependent
@tanstack/start-plugin-core 1.171.24 → 1.171.25 Dependent
@tanstack/start-server-core 1.169.17 → 1.169.18 Dependent
@tanstack/start-static-server-functions 1.167.19 → 1.167.20 Dependent
@tanstack/start-storage-context 1.167.17 → 1.167.18 Dependent
@tanstack/vue-start 1.168.31 → 1.168.32 Dependent
@tanstack/vue-start-client 1.167.19 → 1.167.20 Dependent
@tanstack/vue-start-server 1.167.22 → 1.167.23 Dependent

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: da6ce056-3a70-4fde-a8b2-215fbdc6eb81

📥 Commits

Reviewing files that changed from the base of the PR and between a4d5b8f and 2d639e1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • packages/react-router/package.json
  • packages/router-devtools-core/package.json

📝 Walkthrough

Walkthrough

The PR rewrites router loading around client/server lanes, simplifies match stores, updates React/Solid/Vue rendering and SSR integration, changes HMR refresh behavior, adds extensive lifecycle and hydration tests, and updates loading documentation and end-to-end fixtures.

Changes

Router loading pipeline

Layer / File(s) Summary
Client/server lane orchestration
packages/router-core/src/load-client.ts, packages/router-core/src/load-server.ts, packages/router-core/src/router.ts
Client and server navigation use lane-based contextualization, loading, failure reduction, asset projection, caching, cancellation, and commit flows.
Match and store contracts
packages/router-core/src/Matches.ts, packages/router-core/src/stores.ts, packages/router-core/src/route.ts, packages/router-core/src/redirect.ts
Pending, redirect, lazy-loading, and internal match state shapes are simplified and aligned with semantic match reuse.
Adapter rendering and transitions
packages/react-router/src/*, packages/solid-router/src/*, packages/vue-router/src/*
Pending rendering, reset keys, transition acknowledgement, not-found propagation, hydration behavior, and SSR response statuses are updated across adapters.
Regression coverage
packages/router-core/tests/*, packages/react-router/tests/*, packages/solid-router/tests/*, packages/vue-router/tests/*
Tests cover hydration, preload adoption, abort ownership, pending generations, redirects, lazy chunks, server failures, and lifecycle events.
HMR refresh flow
packages/router-plugin/src/core/hmr/handle-route-update.ts, packages/router-plugin/tests/*
HMR updates rebuild route trees, clear lazy state and path caches, synchronize route exports, and invoke targeted route refreshes.
Documentation and end-to-end fixtures
docs/router/*, e2e/*, benchmarks/memory/*, .changeset/lane-match-loader-rewrite.md
Public loading semantics, cache timing, match state, SSR behavior, issue reproductions, and benchmark cancellation handling are updated.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

  • #2980 — Preload and cache-generation handling covers reuse of active ancestor data across repeated preloads.
  • #3179 — Preload and semantic match handling covers cause and beforeLoad behavior across cached and active matches.
  • #3928 — Loader flight cancellation and abort-aware result handling are directly covered by the client lane pipeline and regression tests.
  • #4614 — Selective SSR preload context behavior is covered by the cached-parent end-to-end test.
  • #7283 — Solid selective SSR hydration for ssr: false and ssr: 'data-only' pending routes is covered by the DEV-mode end-to-end suite.
  • #7379 — Direct-load head({ matches }) context and loader data population are covered by router-core tests.
  • #7457 — Initial redirects after asynchronous beforeLoad are covered by a React end-to-end reproduction.
  • #7815 — Scroll-paint timing is covered by the scroll-restoration end-to-end test.

Possibly related PRs

  • TanStack/router#7422 — Shares the HMR route-update implementation and route refresh behavior.
  • TanStack/router#7596 — Overlaps React match selection, pending rendering, and not-found handling.
  • TanStack/router#6704 — Shares the removal of pending-match state and migration toward match-state-driven rendering.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive Most linked issues have matching code and regression tests, but the summaries don't prove every direct issue is fully covered (notably #7815), so full compliance can't be confirmed. Provide the missing fix-file summaries or an issue-to-file map for the remaining direct issues, especially scroll restoration #7815, so coverage can be verified.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and directly summarizes the main change: a router-core lane match loader rewrite.
Out of Scope Changes check ✅ Passed The changes stay within the router rewrite scope and are supported by targeted tests/docs; no clear unrelated code changes stand out.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-router-core-lane-match-loader

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Benchmarks

  • Commit: 1cfa013f679e
  • Measured at: 2026-07-23T22:17:44.522Z
  • Baseline source: history:88f366ab8e04
  • Dashboard: bundle-size history

The following scenarios have bundle-size changes compared with the baseline:

Scenario Current (gzip) Delta vs baseline Initial gzip Raw Brotli Trend
react-router.minimal 87.37 KiB +21 B (+0.02%) 87.23 KiB 269.79 KiB 76.02 KiB ▁▁▁▁▁▁▁▁▁▁▁█
react-router.full 91.14 KiB +75 B (+0.08%) 91.00 KiB 281.80 KiB 79.37 KiB ▁▁▁▁▁▁▁▁▁▁▁█
solid-router.minimal 35.07 KiB -466 B (-1.28%) 34.95 KiB 100.56 KiB 31.65 KiB ███████████▁
solid-router.full 40.16 KiB -434 B (-1.04%) 40.03 KiB 115.79 KiB 36.16 KiB ███████████▁
vue-router.minimal 52.36 KiB -655 B (-1.21%) 52.23 KiB 143.72 KiB 47.18 KiB ███████████▁
vue-router.full 58.32 KiB -633 B (-1.05%) 58.19 KiB 162.50 KiB 52.34 KiB ███████████▁
react-start.minimal 102.38 KiB +408 B (+0.39%) 102.25 KiB 318.91 KiB 88.83 KiB ▁▁▁▁▁▁▁▁▁▁▁█
react-start.deferred-hydration 103.12 KiB +406 B (+0.39%) 102.27 KiB 320.28 KiB 89.52 KiB ▁▁▁▁▁▁▁▁▁▁▁█
react-start.full 105.71 KiB +354 B (+0.33%) 105.57 KiB 328.91 KiB 91.72 KiB ▁▁▁▁▁▁▁▁▁▁▁█
react-start.rsbuild.minimal 100.05 KiB +383 B (+0.38%) 99.88 KiB 313.36 KiB 86.25 KiB ▁▁▁▁▁▁▁▁▁▁▁█
react-start.rsbuild.minimal-iife 100.45 KiB +381 B (+0.37%) 100.29 KiB 314.29 KiB 86.69 KiB ▁▁▁▁▁▁▁▁▁▁▁█
react-start.rsbuild.full 103.39 KiB +513 B (+0.49%) 103.22 KiB 323.50 KiB 89.08 KiB ▁▁▁▁▁▁▁▁▁▁▁█
solid-start.minimal 49.95 KiB +349 B (+0.69%) 49.82 KiB 148.56 KiB 44.34 KiB ▁▁▁▁▁▁▁▁▁▁▁█
solid-start.deferred-hydration 53.22 KiB +357 B (+0.66%) 49.88 KiB 156.60 KiB 47.33 KiB ▁▁▁▁▁▁▁▁▁▁▁█
solid-start.full 55.27 KiB -158 B (-0.28%) 55.14 KiB 164.35 KiB 48.91 KiB ███████████▁
vue-start.minimal 70.73 KiB -304 B (-0.42%) 70.60 KiB 201.60 KiB 62.81 KiB ███████████▁
vue-start.full 74.70 KiB -344 B (-0.45%) 74.57 KiB 214.21 KiB 66.38 KiB ███████████▁

Current gzip tracks all emitted client JS chunks. Initial gzip tracks only the entry/import graph. Trend sparkline is historical current gzip ending with this PR measurement; lower is better.

@pkg-pr-new

pkg-pr-new Bot commented Jul 13, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@7805

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@7805

@tanstack/eslint-plugin-start

npm i https://pkg.pr.new/@tanstack/eslint-plugin-start@7805

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@7805

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@7805

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@7805

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@7805

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@7805

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@7805

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@7805

@tanstack/react-start-rsc

npm i https://pkg.pr.new/@tanstack/react-start-rsc@7805

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@7805

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@7805

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@7805

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@7805

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@7805

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@7805

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@7805

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@7805

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@7805

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@7805

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@7805

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@7805

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@7805

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@7805

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@7805

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@7805

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@7805

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@7805

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@7805

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@7805

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@7805

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@7805

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@7805

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@7805

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@7805

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@7805

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@7805

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@7805

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@7805

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@7805

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@7805

commit: 2d639e1

@codspeed-hq

codspeed-hq Bot commented Jul 13, 2026

Copy link
Copy Markdown

Merging this PR will regress 14 benchmarks

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 99 improved benchmarks
❌ 24 (👁 10) regressed benchmarks
✅ 57 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation client-control-flow navigation loop (vue) 50.4 ms 56.8 ms -11.37%
Simulation client-async-pipeline navigation loop (vue) 45.9 ms 51.6 ms -10.96%
Simulation client-preload interaction loop (vue) 54.9 ms 60.8 ms -9.71%
Simulation ssr loaders (react) 59.2 ms 65.1 ms -8.98%
Simulation ssr request loop (solid) 146.9 ms 160.3 ms -8.35%
Simulation ssr global-mw server-fn (vue) 59.8 ms 64.3 ms -6.95%
Simulation ssr server-fn raw-response (vue) 56.6 ms 60.3 ms -6.19%
Simulation ssr server-fn not-found (vue) 74.1 ms 78.9 ms -6.06%
Simulation ssr server-fn send-context (vue) 72.9 ms 77.6 ms -6.04%
Simulation ssr server-fn POST (vue) 71.5 ms 75.2 ms -5.03%
Simulation ssr server-fn raw-response (react) 55.2 ms 58.1 ms -4.96%
Simulation ssr server-fn GET (vue) 74.5 ms 77.7 ms -4.09%
Simulation ssr server-fn multipart (vue) 64.3 ms 66.4 ms -3.13%
Simulation ssr server-fn multipart (react) 58.8 ms 60.7 ms -3.1%
Memory mem client interrupted-navigations (solid) 840.8 KB 404 KB ×2.1
Memory mem client interrupted-navigations (react) 756.5 KB 409.3 KB +84.81%
Simulation ssr redirect (solid) 59.5 ms 36.8 ms +61.85%
Simulation ssr redirect (react) 61.3 ms 38.3 ms +60.07%
Simulation ssr redirect (vue) 68.3 ms 49.8 ms +37.16%
Simulation client-mount loop (solid) 58.8 ms 43.5 ms +35.09%
... ... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fix-router-core-lane-match-loader (2d639e1) with main (88f366a)

Open in CodSpeed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/vue-router/src/useMatch.tsx (1)

137-154: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Preserve the generic result type instead of erasing it with any.

Vue.computed<any> allows the implementation to violate the declared ThrowOrOptional<UseMatchResult<...>> contract without a compiler error. Type match and result from the existing generic aliases.

As per coding guidelines, “Use TypeScript strict mode with extensive type safety.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/vue-router/src/useMatch.tsx` around lines 137 - 154, Update the
computed result in the useMatch flow to preserve the existing generic result
type instead of using Vue.computed<any>. Type match and result with the existing
generic aliases, including the declared ThrowOrOptional<UseMatchResult<...>>
contract, so incorrect return values are caught by TypeScript while preserving
the current selection and missing-match behavior.

Source: Coding guidelines

🧹 Nitpick comments (7)
e2e/solid-start/selective-ssr/tests/issue-7283-dev-hydration.spec.ts (1)

27-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use braces for all conditional bodies.

These one-line if statements violate the repository’s TypeScript control-flow convention.

As per coding guidelines, **/*.{ts,tsx,js,jsx} must use curly braces for control statements.

Also applies to: 79-79, 84-84

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/solid-start/selective-ssr/tests/issue-7283-dev-hydration.spec.ts` at line
27, Update the one-line conditional statements in
issue-7283-dev-hydration.spec.ts, including the checks around lines 27, 79, and
84, to wrap each conditional body in curly braces while preserving their
existing behavior.

Source: Coding guidelines

packages/solid-router/tests/transitioner-remount.test.tsx (1)

54-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid discarding location-state type safety.

Assert the partial state shape directly instead of casting to any.

Proposed change
-    expect((router.state.location.state as any).remounted).toBe(true)
+    expect(router.state.location.state).toMatchObject({ remounted: true })

As per coding guidelines, TypeScript files must use strict mode with extensive type safety.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/solid-router/tests/transitioner-remount.test.tsx` at line 54,
Replace the any cast in the remounted-state assertion with a type-safe assertion
of the partial location-state shape, using an appropriate typed access or
narrowing approach so router.state.location.state remains checked by TypeScript.

Source: Coding guidelines

packages/router-core/tests/fatal-load-rejection.test.ts (1)

25-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Model the error component without bypassing its route contract.

as any prevents this test from detecting changes to the errorComponent interface. Use a callable mock component with its preload property attached, matching the runtime shape used elsewhere.

Proposed fix
+    const ErrorComponent = Object.assign(() => null, {
+      preload: errorComponentPreload,
+    })
+
     const rootRoute = new BaseRootRoute({
       loader: () => 'root data',
-      errorComponent: { preload: errorComponentPreload } as any,
+      errorComponent: ErrorComponent,
     })

As per coding guidelines, TypeScript files must use strict mode with extensive type safety.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/router-core/tests/fatal-load-rejection.test.ts` around lines 25 -
30, Update the errorComponent setup in the BaseRootRoute test to use a typed
callable mock component with its preload property attached, matching the runtime
component shape. Remove the as any cast so TypeScript validates the
errorComponent contract and the test catches interface changes.

Source: Coding guidelines

packages/router-core/tests/issue-6371-search-default-normalization-abort.test.ts (1)

60-75: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the canonical replacement setup type-checked.

Both as any casts allow this regression test to keep compiling if buildLocation or commitLocation changes incompatibly. Please use their declared/internal option types or a typed helper for the Transitioner operation being reproduced.

As per coding guidelines, TypeScript files must use strict mode with extensive type safety.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/router-core/tests/issue-6371-search-default-normalization-abort.test.ts`
around lines 60 - 75, Remove the as any casts from the buildLocation and
commitLocation calls in this regression test. Use the declared option types or a
typed helper representing the Transitioner operation so both canonical
replacement setup calls remain strictly type-checked while preserving their
existing behavior.

Source: Coding guidelines

packages/router-core/tests/issue-4444-param-parse-error-lazy-child.test.ts (1)

19-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert that the lazy child chunk was never requested.

The test can currently pass even if lazyFn runs before the child is trimmed, leaving the documented regression partially uncovered.

Proposed assertion
 expect(
   router.state.matches.find((match) => match.status === 'pending'),
 ).toBeUndefined()
+expect(lazyFn).not.toHaveBeenCalled()
 expect(router.state.isLoading).toBe(false)

Also applies to: 60-68

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/router-core/tests/issue-4444-param-parse-error-lazy-child.test.ts`
around lines 19 - 21, Update the test using the lazyFn mock so it explicitly
asserts lazyFn was never called when the child route is trimmed after the
parameter parse error. Place the assertion after the relevant navigation or
error-handling flow, preserving the existing test behavior while verifying the
lazy child chunk is not requested.
packages/react-router/tests/transactional-loading.test.tsx (1)

130-148: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Capture every committed pair to verify atomic publication.

The final sequential assertions can miss a transient mixed-generation render after childRefresh resolves. Record parent/child values on each committed render and assert that neither parent-v2/child-v1 nor parent-v1/child-v2 occurs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/react-router/tests/transactional-loading.test.tsx` around lines 130
- 148, Update the transactional loading test around the final refresh sequence
to record the parent and child values on every committed render, then assert no
mixed-generation pair occurs: parent-v2 with child-v1 or parent-v1 with
child-v2. Keep the existing final-state assertions and use the
render-observation mechanism already provided by the test setup.
packages/router-core/src/router.ts (1)

1330-1338: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Silent catch {} hides listener failures.

Swallowing all listener exceptions keeps one bad listener from breaking others, but the fully empty catch also hides real bugs during development. Consider logging in non-production.

♻️ Suggested dev logging
       if (listener.eventType === routerEvent.type) {
         try {
           listener.fn(routerEvent)
-        } catch {}
+        } catch (err) {
+          if (process.env.NODE_ENV !== 'production') {
+            console.error(
+              `Error in router event listener for "${routerEvent.type}":`,
+              err,
+            )
+          }
+        }
       }

If tests assert fully-silent behavior, feel free to disregard.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/router-core/src/router.ts` around lines 1330 - 1338, Update the
catch block in the emit method to retain listener isolation while reporting
listener exceptions in non-production environments. Preserve the existing
behavior of continuing to notify other subscribers and keeping production
logging silent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/solid-start/selective-ssr/src/routes/ssr-false-pending-min.tsx`:
- Around line 6-13: Update recordEvent to avoid casting window to any by
declaring a local Window augmentation for the __events event buffer, then
initialize and append through window.__events. Preserve the existing server
guard and event shape, including the performance timestamp.

In `@packages/react-router/tests/router.test.tsx`:
- Around line 2463-2467: Update the navigation assertion in the router test to
target the parent route’s specific not-found boundary, using its unique test
identifier or boundary-specific text instead of the broad “Not Found” match;
keep the existing home-page and navigation steps unchanged.

In `@packages/router-core/tests/issue-6221-head-waits-for-loader.test.ts`:
- Line 23: Update the authentication check in the relevant test to wrap the
notFound call inside curly braces, preserving the existing condition and
behavior.

In `@packages/solid-router/src/Transitioner.tsx`:
- Around line 47-65: Move the Solid.onCleanup registration for unsub immediately
after router.history.subscribe(router.load), before the early return in the
Transitioner setup. Keep the existing cleanup callback unchanged and remove the
later registration so every execution path disposes the history subscription.

In `@packages/solid-router/tests/on-rendered-change-info.test.tsx`:
- Around line 44-61: Update the onRendered transition handling to call
getLocationChangeInfo with the previously rendered location as the first
argument and the latest resolved location as the second. Ensure fromLocation,
toLocation, and change flags reflect the actual transition, including same-href
state changes; locate the change in the code that constructs the onRendered
event.

In `@packages/vue-router/tests/pending-fallback-promise-replacement.test.tsx`:
- Around line 13-18: Update the afterEach cleanup hook to drain and await all
testCleanups while fake timers remain active, then restore real timers in a
finally block so timer state is reset even if cleanup fails. Preserve the
existing cleanup() call after the callbacks settle.

---

Outside diff comments:
In `@packages/vue-router/src/useMatch.tsx`:
- Around line 137-154: Update the computed result in the useMatch flow to
preserve the existing generic result type instead of using Vue.computed<any>.
Type match and result with the existing generic aliases, including the declared
ThrowOrOptional<UseMatchResult<...>> contract, so incorrect return values are
caught by TypeScript while preserving the current selection and missing-match
behavior.

---

Nitpick comments:
In `@e2e/solid-start/selective-ssr/tests/issue-7283-dev-hydration.spec.ts`:
- Line 27: Update the one-line conditional statements in
issue-7283-dev-hydration.spec.ts, including the checks around lines 27, 79, and
84, to wrap each conditional body in curly braces while preserving their
existing behavior.

In `@packages/react-router/tests/transactional-loading.test.tsx`:
- Around line 130-148: Update the transactional loading test around the final
refresh sequence to record the parent and child values on every committed
render, then assert no mixed-generation pair occurs: parent-v2 with child-v1 or
parent-v1 with child-v2. Keep the existing final-state assertions and use the
render-observation mechanism already provided by the test setup.

In `@packages/router-core/src/router.ts`:
- Around line 1330-1338: Update the catch block in the emit method to retain
listener isolation while reporting listener exceptions in non-production
environments. Preserve the existing behavior of continuing to notify other
subscribers and keeping production logging silent.

In `@packages/router-core/tests/fatal-load-rejection.test.ts`:
- Around line 25-30: Update the errorComponent setup in the BaseRootRoute test
to use a typed callable mock component with its preload property attached,
matching the runtime component shape. Remove the as any cast so TypeScript
validates the errorComponent contract and the test catches interface changes.

In `@packages/router-core/tests/issue-4444-param-parse-error-lazy-child.test.ts`:
- Around line 19-21: Update the test using the lazyFn mock so it explicitly
asserts lazyFn was never called when the child route is trimmed after the
parameter parse error. Place the assertion after the relevant navigation or
error-handling flow, preserving the existing test behavior while verifying the
lazy child chunk is not requested.

In
`@packages/router-core/tests/issue-6371-search-default-normalization-abort.test.ts`:
- Around line 60-75: Remove the as any casts from the buildLocation and
commitLocation calls in this regression test. Use the declared option types or a
typed helper representing the Transitioner operation so both canonical
replacement setup calls remain strictly type-checked while preserving their
existing behavior.

In `@packages/solid-router/tests/transitioner-remount.test.tsx`:
- Line 54: Replace the any cast in the remounted-state assertion with a
type-safe assertion of the partial location-state shape, using an appropriate
typed access or narrowing approach so router.state.location.state remains
checked by TypeScript.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a9eff563-1e9d-4b5e-9e0d-17c99dcf056c

📥 Commits

Reviewing files that changed from the base of the PR and between 41f7bf3 and ceaa4d2.

📒 Files selected for processing (162)
  • benchmarks/memory/client/scenarios/interrupted-navigations/shared.ts
  • e2e/solid-start/selective-ssr/src/routeTree.gen.ts
  • e2e/solid-start/selective-ssr/src/routes/ssr-false-pending-min.tsx
  • e2e/solid-start/selective-ssr/tests/issue-7283-dev-hydration.spec.ts
  • packages/react-router/src/Match.tsx
  • packages/react-router/src/Matches.tsx
  • packages/react-router/src/Transitioner.tsx
  • packages/react-router/src/lazyRouteComponent.tsx
  • packages/react-router/src/ssr/renderRouterToStream.tsx
  • packages/react-router/src/ssr/renderRouterToString.tsx
  • packages/react-router/tests/Matches.test.tsx
  • packages/react-router/tests/ancestor-loader-child-pending-min.test.tsx
  • packages/react-router/tests/component-preload-retry-pending-min.test.tsx
  • packages/react-router/tests/component-preload-retry.test.tsx
  • packages/react-router/tests/errorComponent.test.tsx
  • packages/react-router/tests/hydration-capped-boundary-pending.test.tsx
  • packages/react-router/tests/hydration-terminal-lane.test.tsx
  • packages/react-router/tests/issue-4759-pending-frame.test.tsx
  • packages/react-router/tests/issue-7051-force-pending-suspense.test.tsx
  • packages/react-router/tests/issue-7367-pending-min-redirect.test.tsx
  • packages/react-router/tests/issue-7457-redirect-chain-first-load.test.tsx
  • packages/react-router/tests/issue-7638-invalidate-transition-error.test.tsx
  • packages/react-router/tests/loaders.test.tsx
  • packages/react-router/tests/on-rendered-same-href-state.test.tsx
  • packages/react-router/tests/pending-fallback-promise-replacement.test.tsx
  • packages/react-router/tests/preloaded-mount-resolution.test.tsx
  • packages/react-router/tests/redirect.test.tsx
  • packages/react-router/tests/root-pending-min.test.tsx
  • packages/react-router/tests/router.test.tsx
  • packages/react-router/tests/store-updates-during-navigation.test.tsx
  • packages/react-router/tests/transactional-loading.test.tsx
  • packages/react-router/tests/transitioner-listener-errors.test.tsx
  • packages/react-router/tests/transitioner-render-ack.test.tsx
  • packages/react-router/tests/transitioner-router-swap.test.tsx
  • packages/react-router/tests/useNavigate.test.tsx
  • packages/router-core/src/Matches.ts
  • packages/router-core/src/hydrate.ts
  • packages/router-core/src/isServer/client.ts
  • packages/router-core/src/isServer/development.ts
  • packages/router-core/src/isServer/server.ts
  • packages/router-core/src/load-matches.ts
  • packages/router-core/src/load.client.ts
  • packages/router-core/src/load.server.ts
  • packages/router-core/src/redirect.ts
  • packages/router-core/src/route-chunks.ts
  • packages/router-core/src/route.ts
  • packages/router-core/src/router.ts
  • packages/router-core/src/ssr/createRequestHandler.ts
  • packages/router-core/src/ssr/ssr-client.ts
  • packages/router-core/src/ssr/ssr-server.ts
  • packages/router-core/src/stores.ts
  • packages/router-core/tests/background-assets-stale.test.ts
  • packages/router-core/tests/background-trim-abort.test.ts
  • packages/router-core/tests/blocked-navigation-current-load.test.ts
  • packages/router-core/tests/boundary-component-chunk.test.ts
  • packages/router-core/tests/callbacks.test.ts
  • packages/router-core/tests/chunk-failure-lifecycle.test.ts
  • packages/router-core/tests/client-lane-adversarial.test.ts
  • packages/router-core/tests/fatal-load-rejection.test.ts
  • packages/router-core/tests/granular-stores.test.ts
  • packages/router-core/tests/hydrate.test.ts
  • packages/router-core/tests/hydrated-stay-match-data.test.ts
  • packages/router-core/tests/hydration-asset-context-order.test.ts
  • packages/router-core/tests/hydration-boundary-chunks.test.ts
  • packages/router-core/tests/hydration-currentness.test.ts
  • packages/router-core/tests/invalidate-pre-rematch-failure.test.ts
  • packages/router-core/tests/issue-3928-rapid-reload-abort.test.ts
  • packages/router-core/tests/issue-4078-loader-notfound-root-boundary.test.ts
  • packages/router-core/tests/issue-4444-param-parse-error-lazy-child.test.ts
  • packages/router-core/tests/issue-4476-preload-navigate-abort.test.ts
  • packages/router-core/tests/issue-4572-preload-root-beforeload-flags.test.ts
  • packages/router-core/tests/issue-4684-head-on-beforeload-error.test.ts
  • packages/router-core/tests/issue-5106-hydrated-notfound-boundary.test.ts
  • packages/router-core/tests/issue-6107-preload-chunk-failure.test.ts
  • packages/router-core/tests/issue-6221-head-waits-for-loader.test.ts
  • packages/router-core/tests/issue-6351-fuzzy-notfound-layout.test.ts
  • packages/router-core/tests/issue-6371-search-default-normalization-abort.test.ts
  • packages/router-core/tests/issue-7379-head-matches-direct-load.test.ts
  • packages/router-core/tests/issue-7635-dehydrated-error-child-head.test.ts
  • packages/router-core/tests/load-route-chunk.test.ts
  • packages/router-core/tests/load.test.ts
  • packages/router-core/tests/preflight-reentrant-context.test.ts
  • packages/router-core/tests/preload-adoption.test.ts
  • packages/router-core/tests/preload-background-parent-coherence.test.ts
  • packages/router-core/tests/preload-public-cache-behavior.test.ts
  • packages/router-core/tests/preload-public-signal-lifetime.test.ts
  • packages/router-core/tests/routerTestUtils.ts
  • packages/router-core/tests/serial-failure-foreground-prefix.test.ts
  • packages/router-core/tests/server-async-headers-decorative-hang.test.ts
  • packages/router-core/tests/server-beforeload-preload-flag.test.ts
  • packages/router-core/tests/server-chunk-failure-lifecycle.test.ts
  • packages/router-core/tests/server-concurrent-error-notfound.test.ts
  • packages/router-core/tests/server-headers-asset-failure.test.ts
  • packages/router-core/tests/server-loader-abort-error.test.ts
  • packages/router-core/tests/server-serial-ssr-notfound.test.ts
  • packages/router-core/tests/server-ssr-false-assets.test.ts
  • packages/router-core/tests/server-ssr-option-error.test.ts
  • packages/router-core/tests/stay-match-abort.test.ts
  • packages/router-core/tests/superseded-load-await.test.ts
  • packages/router-devtools-core/src/AgeTicker.tsx
  • packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx
  • packages/router-plugin/src/core/hmr/handle-route-update.ts
  • packages/router-plugin/tests/add-hmr.test.ts
  • packages/router-plugin/tests/add-hmr/snapshots/react/arrow-function@true.tsx
  • packages/router-plugin/tests/add-hmr/snapshots/react/arrow-function@webpack-hot.tsx
  • packages/router-plugin/tests/add-hmr/snapshots/react/createRootRoute-inline-component@true.tsx
  • packages/router-plugin/tests/add-hmr/snapshots/react/createRootRoute@true.tsx
  • packages/router-plugin/tests/add-hmr/snapshots/react/createRootRouteWithContext-type-args@true.tsx
  • packages/router-plugin/tests/add-hmr/snapshots/react/explicit-undefined-component@true.tsx
  • packages/router-plugin/tests/add-hmr/snapshots/react/function-declaration@true.tsx
  • packages/router-plugin/tests/add-hmr/snapshots/react/multi-component@true.tsx
  • packages/router-plugin/tests/add-hmr/snapshots/react/string-literal-keys@true.tsx
  • packages/router-plugin/tests/add-hmr/snapshots/solid/arrow-function@true.tsx
  • packages/router-plugin/tests/handle-route-update.test.ts
  • packages/solid-router/src/ClientOnly.tsx
  • packages/solid-router/src/Match.tsx
  • packages/solid-router/src/Matches.tsx
  • packages/solid-router/src/Transitioner.tsx
  • packages/solid-router/src/lazyRouteComponent.tsx
  • packages/solid-router/src/matchContext.tsx
  • packages/solid-router/src/routerStores.ts
  • packages/solid-router/src/ssr/renderRouterToStream.tsx
  • packages/solid-router/src/ssr/renderRouterToString.tsx
  • packages/solid-router/src/useMatch.tsx
  • packages/solid-router/tests/Transitioner.test.tsx
  • packages/solid-router/tests/component-preload-retry.test.tsx
  • packages/solid-router/tests/link.test.tsx
  • packages/solid-router/tests/loaders.test.tsx
  • packages/solid-router/tests/on-rendered-change-info.test.tsx
  • packages/solid-router/tests/pending-fallback-promise-replacement.test.tsx
  • packages/solid-router/tests/redirect.test.tsx
  • packages/solid-router/tests/router.test.tsx
  • packages/solid-router/tests/same-route-pending-blank.test.tsx
  • packages/solid-router/tests/server/errorComponent.test.tsx
  • packages/solid-router/tests/store-updates-during-navigation.test.tsx
  • packages/solid-router/tests/transitioner-listener-errors.test.tsx
  • packages/solid-router/tests/transitioner-remount.test.tsx
  • packages/solid-router/tests/transitioner-render-ack.test.tsx
  • packages/solid-router/tests/use-match-outgoing-transition.test.tsx
  • packages/start-server-core/src/createStartHandler.ts
  • packages/vue-router/src/Match.tsx
  • packages/vue-router/src/Matches.tsx
  • packages/vue-router/src/Transitioner.tsx
  • packages/vue-router/src/lazyRouteComponent.tsx
  • packages/vue-router/src/matchContext.tsx
  • packages/vue-router/src/routerStores.ts
  • packages/vue-router/src/ssr/renderRouterToStream.tsx
  • packages/vue-router/src/ssr/renderRouterToString.tsx
  • packages/vue-router/src/useMatch.tsx
  • packages/vue-router/tests/Matches.test.tsx
  • packages/vue-router/tests/Transitioner.test.tsx
  • packages/vue-router/tests/component-preload-retry.test.tsx
  • packages/vue-router/tests/hydration-capped-boundary-pending.test.tsx
  • packages/vue-router/tests/link.test.tsx
  • packages/vue-router/tests/loaders.test.tsx
  • packages/vue-router/tests/pending-fallback-promise-replacement.test.tsx
  • packages/vue-router/tests/redirect.test.tsx
  • packages/vue-router/tests/router.test.tsx
  • packages/vue-router/tests/store-updates-during-navigation.test.tsx
  • packages/vue-router/tests/transitioner-idle-after-render.test.tsx
  • packages/vue-router/tests/transitioner-listener-errors.test.tsx
  • packages/vue-router/tests/transitioner-remount-rendered.test.tsx
💤 Files with no reviewable changes (13)
  • packages/router-plugin/tests/add-hmr.test.ts
  • packages/solid-router/src/matchContext.tsx
  • packages/router-core/src/load-matches.ts
  • packages/solid-router/tests/server/errorComponent.test.tsx
  • packages/solid-router/tests/Transitioner.test.tsx
  • packages/router-core/src/redirect.ts
  • packages/vue-router/src/routerStores.ts
  • packages/router-core/src/ssr/ssr-server.ts
  • packages/solid-router/src/routerStores.ts
  • packages/router-core/tests/callbacks.test.ts
  • packages/vue-router/tests/redirect.test.tsx
  • packages/solid-router/tests/redirect.test.tsx
  • benchmarks/memory/client/scenarios/interrupted-navigations/shared.ts

Comment thread e2e/solid-start/selective-ssr/src/routes/ssr-false-pending-min.tsx
Comment thread packages/react-router/tests/router.test.tsx Outdated
Comment thread packages/router-core/tests/issue-6221-head-waits-for-loader.test.ts Outdated
Comment thread packages/solid-router/src/Transitioner.tsx Outdated
Comment thread packages/solid-router/tests/on-rendered-change-info.test.tsx Outdated
@github-actions github-actions Bot added the documentation Everything documentation related label Jul 13, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/router-core/tests/preload-beforeload-reuse.test.ts (1)

222-280: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a same-route loaderDeps case. This test only changes the parent match; it doesn’t cover reusing preloaded child context when the route’s own deps change.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/router-core/tests/preload-beforeload-reuse.test.ts` around lines 222
- 280, Extend the test around childBeforeLoad to add a same-route loaderDeps
scenario where the child route’s own dependencies change between preload and
navigation. Configure childRoute with loaderDeps and assert the preloaded child
context is not reused, including updated context values and the expected preload
flags.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/router-core/tests/preload-beforeload-reuse.test.ts`:
- Around line 242-245: Update the regression case around loaderDeps and context
to preserve type checking for the version contract: add a typed validateSearch
definition for version, replace Record<string, any> with the inferred or
explicit validated search type, and remove the as any casts around preloadRoute,
navigate, and beforeLoad replacement by using typed route refresh helpers or a
type-compatible mock.

---

Nitpick comments:
In `@packages/router-core/tests/preload-beforeload-reuse.test.ts`:
- Around line 222-280: Extend the test around childBeforeLoad to add a
same-route loaderDeps scenario where the child route’s own dependencies change
between preload and navigation. Configure childRoute with loaderDeps and assert
the preloaded child context is not reused, including updated context values and
the expected preload flags.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: beb16cf3-124d-4a1b-ae41-86535af7b3c1

📥 Commits

Reviewing files that changed from the base of the PR and between adf73dd and 6f75f50.

📒 Files selected for processing (3)
  • docs/router/guide/preloading.md
  • packages/router-core/src/load-client.ts
  • packages/router-core/tests/preload-beforeload-reuse.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/router-core/src/load-client.ts

Comment thread packages/router-core/tests/preload-beforeload-reuse.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/router-core/tests/hydration-currentness.test.ts`:
- Around line 205-232: Extract the repeated mockWindow.$_TSR scaffolding in the
hydration currentness tests into a helper such as mockDehydratedRouter,
accepting only the matches array and preserving the shared manifest,
dehydratedData, callbacks, buffer, and initialized values. Replace the
duplicated setups at the referenced test blocks with this helper while keeping
each test’s matches payload unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dae5e328-1744-4525-a06b-e2022da66f47

📥 Commits

Reviewing files that changed from the base of the PR and between 6f75f50 and f4b8934.

📒 Files selected for processing (10)
  • e2e/react-start/basic/src/routes/specialChars/search.tsx
  • e2e/react-start/basic/tests/special-characters.spec.ts
  • packages/react-router/src/Transitioner.tsx
  • packages/router-core/src/load-client.ts
  • packages/router-core/src/router.ts
  • packages/router-core/tests/hydrated-stay-match-data.test.ts
  • packages/router-core/tests/hydration-currentness.test.ts
  • packages/solid-router/src/Transitioner.tsx
  • packages/solid-router/tests/transitioner-render-ack.test.tsx
  • packages/vue-router/src/Transitioner.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/solid-router/tests/transitioner-render-ack.test.tsx
  • packages/react-router/src/Transitioner.tsx
  • packages/router-core/tests/hydrated-stay-match-data.test.ts
  • packages/solid-router/src/Transitioner.tsx
  • packages/vue-router/src/Transitioner.tsx
  • packages/router-core/src/load-client.ts
  • packages/router-core/src/router.ts

Comment thread packages/router-core/tests/hydration-currentness.test.ts Outdated
nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

nx-cloud[bot]

This comment was marked as outdated.

Sheraff added 2 commits July 20, 2026 18:52
* fix(router-core): complete lane match loader rewrite

* fix(router-core): harden match loading lifecycle

* fix(router-core): preserve hydrated context handoff

* bench(memory): accept expected abort errors

* perf(ssr): reduce request cancellation overhead (#7862)
…match-loader

# Conflicts:
#	e2e/react-start/selective-ssr/src/routeTree.gen.ts
#	e2e/solid-start/selective-ssr/src/routeTree.gen.ts

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.

Nx Cloud is proposing a fix for your failed CI:

We updated two stale HMR snapshots (createFileRoute-lowercase-components@true.tsx and createRootRoute-lowercase-components@true.tsx) and replaced the undefined getReferenceRouteCompilerPlugins reference in the test file with the already-imported getFrameworkHmrCompilerPlugins. These changes align the test fixtures with the simplified handleRouteUpdate implementation introduced by the lane match loader rewrite, resolving both the snapshot mismatches and the ReferenceError/TS2304 type error.

Tip

We verified this fix by re-running @tanstack/router-plugin:test:unit, @tanstack/router-plugin:test:types.

Warning

The suggested diff is too large to display here, but you can view it on Nx Cloud ↗


Apply fix via Nx Cloud  Reject fix via Nx Cloud


Or Apply changes locally with:

npx nx-cloud apply-locally k8RL-Il32

Apply fix locally with your editor ↗   View interactive diff ↗



🎓 Learn more about Self-Healing CI on nx.dev

Sheraff and others added 6 commits July 22, 2026 00:43
* fix(router-core): harden lane loading lifecycle

* ci: apply automated fixes

* fix(router-core): optimize lane loading followups

* fix(router-core): simplify redirect limit handling

* refactor(router-core): clarify loader state and caches

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* perf(router): reduce SSR lane loading overhead

* ci: apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* fix(router): address lane loader regressions

* perf(router-core): shave asset-prefix bookkeeping bytes

- rename the internal `_dataOnlyAssetEnd` match field to `_assetEnd`:
  property keys survive minification, so the shorter internal name saves
  bytes at every site in every bundle
- reduce the `_getAssetMatches` guard to a presence check: the field is
  only ever set on hydration presentation clones that already satisfy
  the pending/data-only/error-free/not-not-found conditions, and commits
  clear it (invariant documented at the guard)
- clone-then-patch the hydration handoff splice instead of spreading a
  conditional object per element, and drop the unreachable zero guard in
  `_getAssetMatches`

Measured (gzip, vs PR tip): react-router.full -43 B, vue-router.full
-35 B, react-router.minimal -8 B. All unit suites green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(router-devtools): preload lazy panel

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sheraff added 4 commits July 23, 2026 15:35
…7883)

* fix(router): final-review regressions, changeset, and byte recovery

Fixes the regressions vs main found in the final review of #7805:

- restore history-subscription cleanup on router provider unmount in all
  three adapters (react returns the unsubscribe unconditionally, solid
  uses onCleanup, vue uses onUnmounted), pinned by new
  transitioner-remount tests — a discarded router could previously keep
  loading on back/forward as a zombie
- same-destination navigations now join the in-flight transaction
  instead of aborting and restarting it (double-click no longer reruns
  loaders); reloads and same-location redirects keep restart semantics
- commitMatches cache retention can no longer resurrect a
  one-generation-old loaderData when a newer committed success exists
  for the same match id
- same-location dedup keeps __tempLocation/__tempKey so masked vs real
  same-href navigations commit their state again

Adds the missing release changeset enumerating the removed/changed
public API with migration hints.

Byte recovery: merges rendered-matches.ts, route-chunks.ts and
hydrate.ts into load-client.ts so the client bundle shares gzip
dictionary context across what were separate module boundaries
(-104..-186 gzip B per start scenario; plain router scenarios remain
net-negative vs main and hydration still tree-shakes out of them).

The solid/vue store-update-count pins were re-adjusted after verifying
the published update sequences are byte-identical: the counts only
shifted because a one-microtask timing change moves the tests'
waitFor-sampled window boundary (5 of 7 counts decreased).

* test(router-devtools-core): keep panel chunk warm-up out of the test budget

The cache-replacement test warmed Vite's lazy transform of
BaseTanStackRouterDevtoolsPanel inside the test body, so on slow CI
runners the transform alone could blow the 5s test timeout (observed at
5.89s). Move the warm-up to a beforeAll with its own generous timeout
and give the test itself explicit headroom. Pre-existing flake on the
lane branch tip, surfaced by this PR's CI being the first to run on it.

* refactor(router-core): extend lane typestate to matches and commits

The lane pipeline already carried phase brands at lane granularity
(Lane<'matched'|'contextualized'|'reduced'|'projected'>); this finishes
the pattern at the two granularities it was missing, at zero runtime
cost (all emitted dist JS verified byte-identical):

- settleInto becomes the sole granter of a SettledMatch brand via an
  assertion signature, and cacheLoaderMatch requires it — the
  loader -> settle -> cache ordering is now compiler-enforced. The one
  legitimate phase jump (hydration cache-seeding of already-settled
  dehydrated data) is a single named, commented boundary cast.
- commitMatches/commitRefreshMatches only accept a projected lane's
  matches (LaneMatches<'projected'>), so committing an earlier-phase
  lane no longer compiles.
- LoadTransaction's dev-only refresh triple collapses into one optional
  slot [presentation, handoff?], making a half-armed refresh state
  unrepresentable and shrinking the clear/read sites.
…match-loader

# Conflicts:
#	e2e/react-start/selective-ssr/src/routeTree.gen.ts
#	e2e/react-start/selective-ssr/src/routes/__root.tsx
#	e2e/react-start/selective-ssr/tests/app.spec.ts
#	packages/react-router/tests/component-preload-retry-pending-min.test.tsx
#	packages/react-router/tests/not-found.test.tsx
#	packages/react-router/tests/public-presentation-lane-contract.test.tsx
#	packages/react-router/tests/redirect.test.tsx
#	packages/react-router/tests/transactional-loading.test.tsx
#	packages/react-router/tests/transitioner-remount.test.tsx
#	packages/react-start-client/src/tests/hydrateStart.test.ts
#	packages/router-core/tests/background-trim-abort.test.ts
#	packages/router-core/tests/boundary-component-chunk.test.ts
#	packages/router-core/tests/callbacks.test.ts
#	packages/router-core/tests/client-lane-adversarial.test.ts
#	packages/router-core/tests/error-boundary-cache-generation.test.ts
#	packages/router-core/tests/granular-stores.test.ts
#	packages/router-core/tests/hydrate.test.ts
#	packages/router-core/tests/issue-6221-head-waits-for-loader.test.ts
#	packages/router-core/tests/loader-architecture-regressions.test.ts
#	packages/router-core/tests/loader-self-abort.test.ts
#	packages/router-core/tests/masked-location-state-commit.test.ts
#	packages/router-core/tests/parent-match-promise.test.ts
#	packages/router-core/tests/preload-adoption.test.ts
#	packages/router-core/tests/preload-beforeload-reuse.test.ts
#	packages/router-core/tests/preload-navigation-adoption.test.ts
#	packages/router-core/tests/preload-public-cache-behavior.test.ts
#	packages/router-core/tests/public-client-loading-contract.test.ts
#	packages/router-core/tests/public-preload-lane-contract.test.ts
#	packages/router-core/tests/same-destination-navigation-join.test.ts
#	packages/router-core/tests/server-beforeload-preload-flag.test.ts
#	packages/router-core/tests/server-loader-abort-error.test.ts
#	packages/router-plugin/tests/handle-route-update.test.ts
#	packages/solid-router/tests/component-preload-retry.test.tsx
#	packages/solid-router/tests/createLazyRoute.test.tsx
#	packages/solid-router/tests/loaders.test.tsx
#	packages/solid-start-client/src/tests/hydrateStart.test.ts
#	packages/vue-router/tests/Transitioner.test.tsx
#	packages/vue-router/tests/disableGlobalCatchBoundary.test.tsx
#	packages/vue-router/tests/transitioner-remount-rendered.test.tsx
#	packages/vue-router/tests/transitioner-remount.test.tsx
#	packages/vue-router/tests/useMatch.test.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
e2e/react-router/issue-7120/package.json (1)

14-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Resolve the internal workspace protocol before merging.

These internal dependencies use workspace:^, while the current coding guideline requires workspace:*. The supplied repository learning states that e2e applications conventionally use workspace:^, so please confirm which policy governs this PR. If the current guideline is authoritative, update all three ranges:

Proposed fix
-    "`@tanstack/react-router`": "workspace:^",
-    "`@tanstack/router-plugin`": "workspace:^",
+    "`@tanstack/react-router`": "workspace:*",
+    "`@tanstack/router-plugin`": "workspace:*",
...
-    "`@tanstack/router-e2e-utils`": "workspace:^",
+    "`@tanstack/router-e2e-utils`": "workspace:*",

As per coding guidelines, internal dependencies in package.json must use workspace:*; based on learnings, e2e apps conventionally use workspace:^, so this policy conflict needs explicit resolution.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-router/issue-7120/package.json` around lines 14 - 21, Resolve the
policy conflict for internal workspace dependencies in this package: confirm
whether the current guideline or the e2e convention governs this PR, then update
all three workspace ranges in the package manifest to the authoritative
protocol, using workspace:* if the guideline applies.

Sources: Coding guidelines, Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/lane-match-loader-rewrite.md:
- Around line 2-5: Update the changeset release levels for
`@tanstack/router-core`, `@tanstack/react-router`, `@tanstack/solid-router`, and
`@tanstack/vue-router` from patch to major to reflect the removed public members
and changed StartTransitionFn signature.

In `@e2e/react-router/issue-7457/src/main.tsx`:
- Around line 21-25: Declare the ambient __pendingSeen flag in
e2e/react-router/issue-7457/src/vite-env.d.ts, then replace the any-cast global
access in DefaultPendingComponent within
e2e/react-router/issue-7457/src/main.tsx and the corresponding test access in
e2e/react-router/issue-7457/tests/issue-7457.repro.spec.ts with direct
globalThis.__pendingSeen usage.

---

Nitpick comments:
In `@e2e/react-router/issue-7120/package.json`:
- Around line 14-21: Resolve the policy conflict for internal workspace
dependencies in this package: confirm whether the current guideline or the e2e
convention governs this PR, then update all three workspace ranges in the
package manifest to the authoritative protocol, using workspace:* if the
guideline applies.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 51034e37-ca80-4e45-ba7e-ca5dbe8df417

📥 Commits

Reviewing files that changed from the base of the PR and between f4b8934 and a4d5b8f.

📒 Files selected for processing (46)
  • .changeset/lane-match-loader-rewrite.md
  • benchmarks/memory/server/scenarios/aborted-requests/shared.ts
  • docs/router/api/router/RouteMatchType.md
  • docs/router/api/router/RouteOptionsType.md
  • docs/router/api/router/RouterOptionsType.md
  • docs/router/api/router/RouterStateType.md
  • docs/router/api/router/RouterType.md
  • docs/router/api/router/useChildMatchesHook.md
  • docs/router/api/router/useMatchesHook.md
  • docs/router/api/router/useParentMatchesHook.md
  • docs/router/guide/data-loading.md
  • docs/router/guide/path-params.md
  • docs/router/guide/preloading.md
  • docs/router/how-to/debug-router-issues.md
  • e2e/react-router/issue-7120/index.html
  • e2e/react-router/issue-7120/package.json
  • e2e/react-router/issue-7120/playwright.config.ts
  • e2e/react-router/issue-7120/src/main.tsx
  • e2e/react-router/issue-7120/src/redirectGate.ts
  • e2e/react-router/issue-7120/src/routeTree.gen.ts
  • e2e/react-router/issue-7120/src/routes/__root.tsx
  • e2e/react-router/issue-7120/src/routes/index.tsx
  • e2e/react-router/issue-7120/src/routes/posts.lazy.tsx
  • e2e/react-router/issue-7120/src/routes/posts.tsx
  • e2e/react-router/issue-7120/src/vite-env.d.ts
  • e2e/react-router/issue-7120/tests/issue-7120.repro.spec.ts
  • e2e/react-router/issue-7120/tsconfig.json
  • e2e/react-router/issue-7120/vite.config.ts
  • e2e/react-router/issue-7457/index.html
  • e2e/react-router/issue-7457/package.json
  • e2e/react-router/issue-7457/playwright.config.ts
  • e2e/react-router/issue-7457/src/main.tsx
  • e2e/react-router/issue-7457/src/routeTree.gen.ts
  • e2e/react-router/issue-7457/src/routes/__root.tsx
  • e2e/react-router/issue-7457/src/routes/another.tsx
  • e2e/react-router/issue-7457/src/routes/index.tsx
  • e2e/react-router/issue-7457/src/vite-env.d.ts
  • e2e/react-router/issue-7457/tests/issue-7457.repro.spec.ts
  • e2e/react-router/issue-7457/tsconfig.json
  • e2e/react-router/issue-7457/vite.config.js
  • e2e/react-router/scroll-restoration-sandbox-vite/tests/app.spec.ts
  • e2e/react-start/selective-ssr/src/routes/__root.tsx
  • e2e/react-start/selective-ssr/tests/app.spec.ts
  • e2e/solid-start/selective-ssr/dev-server.ts
  • e2e/solid-start/selective-ssr/playwright.config.ts
  • e2e/solid-start/selective-ssr/tests/issue-7283-dev-hydration.spec.ts

Comment on lines +2 to +5
'@tanstack/router-core': patch
'@tanstack/react-router': patch
'@tanstack/solid-router': patch
'@tanstack/vue-router': patch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== changeset file =="
cat -n .changeset/lane-match-loader-rewrite.md

echo
echo "== repo files mentioning semver / changeset / major release =="
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/.git/**' -e 'semver|major release|patch release|changeset' README* .changeset docs . 2>/dev/null | head -n 200

Repository: TanStack/router

Length of output: 18706


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file list around changesets =="
git ls-files '.changeset/*' | sed -n '1,120p'

echo
echo "== outline of the referenced changeset =="
wc -l .changeset/lane-match-loader-rewrite.md
sed -n '1,120p' .changeset/lane-match-loader-rewrite.md

Repository: TanStack/router

Length of output: 3407


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== .changeset/config.json =="
cat -n .changeset/config.json

echo
echo "== docs / config mentioning patch or major policy =="
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/.git/**' -e 'patch.*major|major.*patch|breaking.*patch|changeset.*patch|changeset.*major|semver policy|version policy|breaking change' .changeset docs README* package.json .github . 2>/dev/null | head -n 200

Repository: TanStack/router

Length of output: 16531


Use a major changeset for the API removals. The affected sections remove public members and change StartTransitionFn’s signature, so patch release metadata is inconsistent with the documented breaking surface.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/lane-match-loader-rewrite.md around lines 2 - 5, Update the
changeset release levels for `@tanstack/router-core`, `@tanstack/react-router`,
`@tanstack/solid-router`, and `@tanstack/vue-router` from patch to major to reflect
the removed public members and changed StartTransitionFn signature.

Comment on lines +21 to +25
function DefaultPendingComponent() {
useEffect(() => {
;(globalThis as any).__pendingSeen = true
}, [])
return <div data-testid="app-pending">loading</div>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd '^tsconfig\.json$' e2e/react-router/issue-7457 -x sh -c '
  echo "--- $1"
  sed -n "1,220p" "$1"
' sh {}

rg -n --glob '*.{ts,tsx,d.ts}' \
  '\(globalThis as any\)\.__pendingSeen|declare global|__pendingSeen' \
  e2e/react-router/issue-7457

Repository: TanStack/router

Length of output: 756


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "--- files"
git ls-files e2e/react-router/issue-7457

echo
echo "--- declaration/global matches"
rg -n --glob 'e2e/react-router/issue-7457/**/*.{ts,tsx,d.ts}' \
  'declare global|interface Window|__pendingSeen|globalThis as any' \
  e2e/react-router/issue-7457

echo
echo "--- tsconfig files"
fd 'tsconfig\.json$' e2e/react-router/issue-7457 -x sh -c '
  echo "### $1"
  sed -n "1,220p" "$1"
' sh {}

Repository: TanStack/router

Length of output: 1377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "--- vite-env.d.ts"
cat -n e2e/react-router/issue-7457/src/vite-env.d.ts

echo
echo "--- package.json"
cat -n e2e/react-router/issue-7457/package.json

echo
echo "--- playwright.config.ts"
cat -n e2e/react-router/issue-7457/playwright.config.ts

Repository: TanStack/router

Length of output: 2095


Declare __pendingSeen instead of casting globalThis to any. Add the ambient flag declaration in e2e/react-router/issue-7457/src/vite-env.d.ts, then use globalThis.__pendingSeen directly in e2e/react-router/issue-7457/src/main.tsx and e2e/react-router/issue-7457/tests/issue-7457.repro.spec.ts.

📍 Affects 2 files
  • e2e/react-router/issue-7457/src/main.tsx#L21-L25 (this comment)
  • e2e/react-router/issue-7457/tests/issue-7457.repro.spec.ts#L29-L31
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-router/issue-7457/src/main.tsx` around lines 21 - 25, Declare the
ambient __pendingSeen flag in e2e/react-router/issue-7457/src/vite-env.d.ts,
then replace the any-cast global access in DefaultPendingComponent within
e2e/react-router/issue-7457/src/main.tsx and the corresponding test access in
e2e/react-router/issue-7457/tests/issue-7457.repro.spec.ts with direct
globalThis.__pendingSeen usage.

Source: Coding guidelines

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