Skip to content

Conversation

@Sheraff
Copy link
Contributor

@Sheraff Sheraff commented Nov 21, 2025

Fix #5912

All things being equal, a shorter route should only be favored over a longer one w/ skipped optional segments if that shorter route is an index route. Otherwise, favor deeper routes, even if that means we have to skip many optional segments.

This changes the expectations for 2 of our existing unit tests, but we didn't have a strong opinion on either of those tests:

  • '/{-$other}/posts/new', '/posts/new' matching path /posts/new
    => used to match /posts/new, with this PR will match /{-$other}/posts/new
  • '/foo/{-$p}.tsx', '/foo/{-$p}/{-$x}.tsx' matching path /foo
    => used to match /foo/{-$p}.tsx, with this PR will match /foo/{-$p}/{-$x}.tsx

Summary by CodeRabbit

  • Bug Fixes

    • Refined route matching so deeper optional segments are preferred in tie situations and index routes correctly win when applicable, improving specificity decisions in complex hierarchies.
  • Tests

    • Updated and added tests to verify new resolution behavior for optional/deeper route chains and index-vs-optional edge cases.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

Walkthrough

This PR fixes route matching when optional parameters coexist with layout routes. The changes modify the early-termination condition in getNodeMatch to require index route status and enhance the tie-breaker logic in isFrameMoreSpecific to consider node depth and index flags, improving specificity comparison for optional parameter chains.

Changes

Cohort / File(s) Summary
Core route matching logic
packages/router-core/src/new-process-route-tree.ts
Modified early-return condition for perfect matches to require node.isIndex alongside statics === partsLength. Expanded isFrameMoreSpecific tie-breaker logic to compare optionals, depth, and index-flag status when dynamics are equal.
Route matching test suite
packages/router-core/tests/new-process-route-tree.test.ts
Updated test expectations to reflect new matching behavior: deeper optional chains now preferred over shallower routes; added test for optional child vs. shorter route preference; expanded edge-case coverage for optional/deeper chain scenarios and index-route precedence.

Sequence Diagram

sequenceDiagram
    participant Router as Route Matcher
    participant Old as Old Logic
    participant New as New Logic
    
    Note over Router,New: Matching "/posts" with optional {-$category}
    
    rect rgb(200, 220, 240)
    Note over Old,New: Perfect match detection
    Old->>Old: Check statics === partsLength?
    Old->>Old: ❌ Early return (missing index check)
    New->>New: Check statics === partsLength && node.isIndex?
    New->>New: ✓ Properly gate early termination
    end
    
    rect rgb(220, 240, 200)
    Note over Old,New: Tie-breaker when dynamics equal
    Old->>Old: Limited comparison
    New->>New: Compare optionals → depth → index flag
    New->>New: ✓ More precise specificity ranking
    end
    
    Note over Router: Result: Layout routes + optional params now match correctly
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Logic density: Route matching tie-breaker logic is intricate; the addition of index-flag and depth comparisons requires careful verification of ordering and edge cases.
  • Behavioral shift: Test expectations changed significantly, indicating non-trivial matching behavior changes that need validation against the reported issue.
  • Scope: Changes are localized to one implementation file, but affect critical routing behavior.

Areas requiring extra attention:

  • Verify that the new node.isIndex requirement in getNodeMatch doesn't inadvertently break other route patterns
  • Confirm the ordering of tie-breaker comparisons (optionals → depth → index) produces correct specificity rankings
  • Validate test scenario coverage matches real-world layout + optional parameter combinations

Possibly related PRs

Suggested labels

package: router-core

Suggested reviewers

  • schiller-manuel
  • nlynzaad

Poem

🐰 A layout route once blocked the way,
Optional chains would lose their say,
Now depth and index flags align,
And matching logic runs just fine—
No more ghosts in empty slots today! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: fixing route matching to favor index routes or deepest non-index routes, which directly addresses the linked issue about optional parameter matching.
Linked Issues check ✅ Passed The code changes implement logic to prioritize index route matches and deeper optional chains, directly fixing the issue where optional param routes failed to match base URLs when layout routes existed.
Out of Scope Changes check ✅ Passed All changes are scoped to the route matching logic in new-process-route-tree.ts and its tests, directly addressing the optional parameter matching issue without introducing unrelated modifications.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-router-core-favor-index-or-deepest-route-matches

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

@nx-cloud
Copy link

nx-cloud bot commented Nov 21, 2025

View your CI Pipeline Execution ↗ for commit 6300434

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

☁️ Nx Cloud last updated this comment at 2025-11-21 17:35:28 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 21, 2025

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@5933

@tanstack/directive-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/directive-functions-plugin@5933

@tanstack/eslint-plugin-router

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

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@5933

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@5933

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@5933

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@5933

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/server-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/server-functions-plugin@5933

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@5933

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@5933

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@5933

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@5933

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@5933

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@5933

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@5933

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@5933

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@5933

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@5933

commit: 6300434

@Sheraff Sheraff merged commit 62a761c into main Nov 21, 2025
6 checks passed
@Sheraff Sheraff deleted the fix-router-core-favor-index-or-deepest-route-matches branch November 21, 2025 22:55
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.

Layout routes cause optional params to fail to match

3 participants