Skip to content

fix(router-core): buildLocation should interpolatePath w/ stringified params for skipRouteOnParseError routes#6491

Open
Sheraff wants to merge 8 commits intomainfrom
fix-router-core-build-location-skip-on-parse-interpolate-stringified-params
Open

fix(router-core): buildLocation should interpolatePath w/ stringified params for skipRouteOnParseError routes#6491
Sheraff wants to merge 8 commits intomainfrom
fix-router-core-build-location-skip-on-parse-interpolate-stringified-params

Conversation

@Sheraff
Copy link
Contributor

@Sheraff Sheraff commented Jan 24, 2026

Fixes #6490

Warning

I'm not 100% convinced this is a good idea.

Problem & proposed solution:
Currently before we look for a branch match in the route tree, we interpolatePath using to and the raw params provided by the user. This bypasses the params.stringify option.

Up until now, this hasn't been an issue because all the path params always accept any string (we can imagine cases where this would in fact have been an issue, for example it the stringification adds a prefix, and then with the prefix it's actually another route that is matched, but such cases have seemingly never been reported).

However, with the introduction of skipRouteOnParseError, we may now use params.parse in the matching algorithm, and params.parse expects its inputs to have gone through params.stringify (see #6490). And if they didn't, this can result in incorrect branch matches.

This PR proposes that we call interpolatePath after the params have gone through params.stringify. This is a little weird because to do this we have to "trust" that the to parameter is correct, but then we still run the match algorithm, which could return a different branch (i.e. a different to).

Note

Maybe to cover edge-cases we could re-run interpolatePath and getMatchedRoutes on the original raw params if the resulting matched branch isn't the same as the one we "naively inferred" through buildRouteBranch. But that would be quite the overhead.

Possible issues:

  • slower than not doing it
  • sometimes people pre-interpolate their to props, and then it wouldn't match anything in the routesByPath lookup
  • sometimes once interpolated, the pathname will actually match another route than the original to (intended behavior) but by then we will have stringified the params using the original to (weird behavior?)
  • aren't there other places in the codebase where we just encodeURIComponent the params instead of going through params.stringify? I have a hard time believing we always know which route branch we're working on
  • ??

However, if you respect the types, and you don't have a crazy route setup that makes conflict likely, then this is pretty powerful (see original issue).

The alternatives are:

  • to simply forbid the combined use of skipRouteOnParseError.params: true and params.stringify
  • to use a separate method for skipRouteOnParseError.params than the one used for "reversing the stringification"

🤷

Summary by CodeRabbit

  • New Features

    • Route-building utility is now publicly available for external use.
  • Improvements

    • More robust path interpolation when routes use custom param parse/stringify, including safer handling to preserve intended destinations when parse errors are configurable.
  • Tests

    • Added tests covering parameter stringification and skip-on-parse-error behavior to validate resolved pathnames.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 24, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Exports buildRouteBranch and adds a pre-interpolation param stringification pass in buildLocation that uses route-branch stringifiers when skipRouteOnParseError.params is enabled; adds tests validating the behavior.

Changes

Cohort / File(s) Summary
Route Tree Module Export
packages/router-core/src/new-process-route-tree.ts
Adds export to buildRouteBranch, making it part of the module's public API.
Parameter Stringification Preprocessing
packages/router-core/src/router.ts
Imports buildRouteBranch and introduces prestringifiedParams flow: pre-stringify params across a route branch when skipRouteOnParseError.params is set, use those values in interpolatePath, track attempted prestringify and clear it if destination mismatches, and preserve prior behavior otherwise.
Test Coverage
packages/router-core/tests/build-location.test.ts
Adds tests for buildLocation with a route using custom parse/stringify and skipRouteOnParseError.params, asserting expected pathname outcome.

Sequence Diagram(s)

sequenceDiagram
  participant Router as Router.buildLocation
  participant Branch as buildRouteBranch
  participant Route as Route.stringify
  participant Interp as interpolatePath
  participant Dest as DestinationResolver

  Router->>Branch: request branch info (stringifiers) for target route
  Branch-->>Router: route branch (stringifiers)
  Router->>Route: apply stringify across branch -> prestringifiedParams
  Route-->>Router: prestringifiedParams
  Router->>Interp: interpolatePath(nextTo, prestringifiedParams)
  Interp-->>Router: interpolatedNextTo
  Router->>Dest: resolve destination with interpolatedNextTo
  Dest-->>Router: resolved destination (fullPath)
  alt destination matches trimmed target
    Router->>Router: use interpolatedNextTo as nextPathname
  else destination mismatch
    Router->>Route: compute stringifiedParams fallback (no prestringified)
    Route-->>Router: stringifiedParams
    Router->>Interp: interpolatePath(nextTo, stringifiedParams)
    Interp-->>Router: nextPathname
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • schiller-manuel
  • nlynzaad

Poem

🐇 I hopped the branch and trimmed each name,
I wove their strings so paths stay tame,
I prepped the params before they flew,
Now links resolve and routes pass through,
A happy hop — the router's game! 🌿

🚥 Pre-merge checks | ✅ 5 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: fixing buildLocation to use stringified params with interpolatePath for skipRouteOnParseError routes, which directly addresses the core issue.
Linked Issues check ✅ Passed The PR implementation fully addresses issue #6490 by introducing prestringifiedParams flow to ensure stringified params are used in path interpolation when skipRouteOnParseError is enabled, preventing incorrect URL generation.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the skipRouteOnParseError stringification issue: exporting buildRouteBranch, updating buildLocation logic, and adding comprehensive tests for the fix.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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-build-location-skip-on-parse-interpolate-stringified-params

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

@nx-cloud
Copy link

nx-cloud bot commented Jan 24, 2026

View your CI Pipeline Execution ↗ for commit a3c3a56

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

☁️ Nx Cloud last updated this comment at 2026-02-15 08:34:45 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 24, 2026

More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@6491

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6491

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: a3c3a56

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/router-core/src/router.ts`:
- Around line 1803-1807: The interpolatedNextTo is currently built from
nextParams (parsed values) but later code sometimes needs the stringified values
in prestringifiedParams; change the interpolation so that when
prestringifiedParams is provided you call interpolatePath with params:
prestringifiedParams (and same decoder) instead of nextParams, or alternatively
compute a second value (e.g., interpolatedPrestringifiedNextTo) by calling
interpolatePath({ path: nextTo, params: prestringifiedParams, decoder:
this.pathParamsDecoder }) and use that result wherever the code currently
branches on prestringifiedParams (including the return path and any route
matching that relies on interpolatedNextTo). Ensure the unique symbols involved
are interpolatePath, interpolatedNextTo (or new
interpolatedPrestringifiedNextTo), nextParams, and prestringifiedParams so the
correct interpolated pathname is returned and used for matching.

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.

skipRouteOnParseError causes incorrect param stringification

1 participant

Comments