Skip to content

fix(router-core): use configured search serializer for loader dependency keys#7818

Closed
gonzoblasco wants to merge 2 commits into
TanStack:mainfrom
gonzoblasco:fix/7787-loader-deps-search-serializer
Closed

fix(router-core): use configured search serializer for loader dependency keys#7818
gonzoblasco wants to merge 2 commits into
TanStack:mainfrom
gonzoblasco:fix/7787-loader-deps-search-serializer

Conversation

@gonzoblasco

@gonzoblasco gonzoblasco commented Jul 15, 2026

Copy link
Copy Markdown

Description

The loaderDepsHash was hardcoded to JSON.stringify, ignoring the router's configured stringifySearch option. This meant custom search serializers that support values JSON.stringify cannot handle (e.g. bigint, Set, Map) would fail or produce incorrect hashes when those values were used in loaderDeps.

Root Cause

In packages/router-core/src/router.ts, line 1538:

const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : ''

JSON.stringify is used regardless of the stringifySearch option configured on the router. If a user configures a custom stringifySearch to support non-JSON-serializable values in search params, those same values cannot be used in loaderDeps because the hash will throw or produce incorrect results.

Fix

Replace JSON.stringify(loaderDeps) with this.options.stringifySearch(loaderDeps) so the hash uses the same serializer configured for URL search state.

- const loaderDepsHash = loaderDeps ? JSON.stringify(loaderDeps) : ''
+ const loaderDepsHash = loaderDeps
+   ? this.options.stringifySearch(loaderDeps)
+   : ''

This continues the work started in #4713.

Tests

Added packages/router-core/tests/loader-deps-serializer.test.ts with two regression tests:

  1. Custom serializer with bigint support — verifies that a router configured with a custom stringifySearch supporting bigint can use bigint values in loaderDeps without throwing (which JSON.stringify would do with TypeError: Do not know how to serialize a BigInt).

  2. Different deps produce different match IDs — verifies that changing loaderDeps values produces different match IDs, confirming the hash is still deterministic and distinguishable.

Verification

  • ✅ New tests pass
  • ✅ Existing callbacks.test.ts (9 tests) — all pass
  • ✅ Existing match-params.test.ts (23 tests) — all pass
  • ⚠️ load.test.ts — 1 pre-existing flaky test fails (skip if pending preload (redirect)) — confirmed failing on main without this change

Fixes #7787

Summary by CodeRabbit

  • Bug Fixes
    • Improved route matching for loader dependencies by deriving the match identity from the router’s configured search serializer.
    • Prevented navigation failures when loader dependencies include values such as bigint.
    • Ensured route loaders refresh correctly when relevant search filter values change.
  • Tests
    • Added coverage to verify search serialization behavior and correct loader invocation across differing search filter values.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

Loader dependency cache keys now use the router’s configured search serializer. Regression tests cover BigInt-compatible serialization and distinct cache identities for changing loader dependency values.

Changes

Loader dependency serialization

Layer / File(s) Summary
Use configured serializer for loader keys
packages/router-core/src/router.ts, packages/router-core/tests/loader-deps-serializer.test.ts
loaderDepsHash uses stringifySearch instead of JSON.stringify; tests cover BigInt serialization, differing match IDs, and loader dependency values.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested labels: package: router-core

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely matches the main router-core serializer change.
Linked Issues check ✅ Passed The code and tests satisfy #7787 by using the configured serializer and verifying cache identity changes.
Out of Scope Changes check ✅ Passed The changes are limited to the serializer fix and its regression tests, with no obvious unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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/loader-deps-serializer.test.ts`:
- Line 10: Update the bigint handling condition in the loader dependency
serializer to wrap its single-line return body in curly braces, preserving the
existing serialization behavior and value.toString()n output.
🪄 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: 51396397-c8c3-41fa-8349-d74017ce065a

📥 Commits

Reviewing files that changed from the base of the PR and between 11a6a0d and 508c851.

📒 Files selected for processing (2)
  • packages/router-core/src/router.ts
  • packages/router-core/tests/loader-deps-serializer.test.ts

Comment thread packages/router-core/tests/loader-deps-serializer.test.ts Outdated
@gonzoblasco gonzoblasco force-pushed the fix/7787-loader-deps-search-serializer branch from 508c851 to 80ed772 Compare July 15, 2026 01:23

@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.

🧹 Nitpick comments (1)
HANDOFF.md (1)

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

Separate mutable project status from durable handoff instructions.

The star count, PR state, estimated review window, and “Qué sigue” items will become stale as the work progresses. Add a “last updated” date and link to authoritative PR metadata, or move this tracking out of HANDOFF.md so future readers do not treat outdated status as current.

Also applies to: 18-39

🤖 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 `@HANDOFF.md` around lines 4 - 7, Separate mutable project-status details from
the durable handoff guidance in HANDOFF.md: move the star count, PR state,
review estimate, and “Qué sigue” tracking to an appropriate status location, or
clearly mark that section with a last-updated date and authoritative PR metadata
link. Keep HANDOFF.md focused on stable instructions and ensure future readers
can distinguish current status from durable guidance.
🤖 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.

Nitpick comments:
In `@HANDOFF.md`:
- Around line 4-7: Separate mutable project-status details from the durable
handoff guidance in HANDOFF.md: move the star count, PR state, review estimate,
and “Qué sigue” tracking to an appropriate status location, or clearly mark that
section with a last-updated date and authoritative PR metadata link. Keep
HANDOFF.md focused on stable instructions and ensure future readers can
distinguish current status from durable guidance.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 46fe2442-45f1-4c00-a3cf-e785fb85fb3d

📥 Commits

Reviewing files that changed from the base of the PR and between 508c851 and 80ed772.

📒 Files selected for processing (3)
  • HANDOFF.md
  • packages/router-core/src/router.ts
  • packages/router-core/tests/loader-deps-serializer.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/router-core/tests/loader-deps-serializer.test.ts
  • packages/router-core/src/router.ts

Comment thread HANDOFF.md Outdated
@gonzoblasco gonzoblasco force-pushed the fix/7787-loader-deps-search-serializer branch 2 times, most recently from 0ce9fa4 to f7a3eb5 Compare July 15, 2026 07:42
…ncy keys

The loaderDepsHash was hardcoded to JSON.stringify, ignoring the
router's configured stringifySearch option. This meant custom search
serializers that support values JSON.stringify cannot handle (e.g.
bigint, Set, Map) would fail when those values were used in loaderDeps.

Replace JSON.stringify(loaderDeps) with this.options.stringifySearch(
loaderDeps) so the hash uses the same serializer configured for URL
search state. This continues the work started in TanStack#4713.

Add regression tests verifying:
- Custom serializer with bigint support works for loaderDeps
- Different deps values produce different match IDs

Fixes TanStack#7787
@gonzoblasco gonzoblasco force-pushed the fix/7787-loader-deps-search-serializer branch from f7a3eb5 to 4e78e57 Compare July 15, 2026 07:43
@gonzoblasco

Copy link
Copy Markdown
Author

Hi @LadyBluenotes — done! The file has been removed from this PR.

@nx-cloud

nx-cloud Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit beb40e4

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

☁️ Nx Cloud last updated this comment at 2026-07-15 14:31:09 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jul 15, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/eslint-plugin-start

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-rsc

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: beb40e4

@codspeed-hq

codspeed-hq Bot commented Jul 15, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 81.45%

⚠️ 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

⚡ 3 improved benchmarks
❌ 5 regressed benchmarks
✅ 172 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory mem server error-paths unmatched (react) 264.2 KB 571.6 KB -53.78%
Memory mem server peak-large-page (solid) 771.4 KB 961.7 KB -19.79%
Memory mem server streaming-peak chunked (vue) 11.1 MB 13.7 MB -19.43%
Memory mem server error-paths not-found (react) 267 KB 277.4 KB -3.73%
Simulation client-async-pipeline navigation loop (react) 49.8 ms 51.7 ms -3.57%
Memory mem server server-fn-churn (vue) 3,985.2 KB 263.4 KB ×15
Memory mem server server-fn-churn (solid) 3,825.7 KB 273.8 KB ×14
Memory mem server error-paths redirect (vue) 611.4 KB 305 KB ×2

Tip

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


Comparing gonzoblasco:fix/7787-loader-deps-search-serializer (beb40e4) with main (0b178a7)

Open in CodSpeed

@gonzoblasco

Copy link
Copy Markdown
Author

Thanks for the benchmark report! I want to acknowledge the flagged regressions.

The change in this PR is minimal — replacing JSON.stringify(loaderDeps) with this.options.stringifySearch(loaderDeps) in router.ts. This is a 2-line change that doesn't introduce new allocations or data structures.

Looking at the report:

  • CodSpeed itself flags "Different runtime environments detected" for this comparison, which can affect accuracy of memory benchmarks
  • The 3 improved benchmarks show significant gains (×15, ×14, ×2 memory improvements), which further suggests the deltas are environmental noise rather than real impact from this change
  • The largest regression (-53.78% on mem server error-paths unmatched (react): 264KB → 572KB) is unlikely caused by swapping a serializer function call

I believe these are false positives from the runtime environment differences, but happy to investigate further if maintainers think otherwise.

@LadyBluenotes — the HANDOFF.md file has been removed and CI is green. Ready for re-review when you have a chance 🙏

@LadyBluenotes

LadyBluenotes commented Jul 15, 2026

Copy link
Copy Markdown
Member

Thanks for the benchmark report! I want to acknowledge the flagged regressions.

The change in this PR is minimal — replacing JSON.stringify(loaderDeps) with this.options.stringifySearch(loaderDeps) in router.ts. This is a 2-line change that doesn't introduce new allocations or data structures.

Looking at the report:

* CodSpeed itself flags "Different runtime environments detected" for this comparison, which can affect accuracy of memory benchmarks

* The 3 improved benchmarks show significant gains (×15, ×14, ×2 memory improvements), which further suggests the deltas are environmental noise rather than real impact from this change

* The largest regression (-53.78% on `mem server error-paths unmatched (react)`: 264KB → 572KB) is unlikely caused by swapping a serializer function call

I believe these are false positives from the runtime environment differences, but happy to investigate further if maintainers think otherwise.

@LadyBluenotes — the HANDOFF.md file has been removed and CI is green. Ready for re-review when you have a chance 🙏

I want to be candid: this reply feel like it's coming from an AI agent rather than from a human directly. AI assistance is fine, but I need to know that you understand and have personally verified the changes you’re submitting. If it continues to feel like an agent is speaking on your behalf, I’ll close the PR.

As for the benchmark results, these benchmarks are known to be flaky, so the reported changes can be taken with a grain of salt.

@schiller-manuel

Copy link
Copy Markdown
Collaborator

a loader dep CAN be a search param, but it doesnt have to be. tying it to the search stringifier is not the way

@gonzoblasco

Copy link
Copy Markdown
Author

Hi, my name is Gonzalo, I'm who is creating this PRs. I'm testing how this agent I created with OpenClaw allowed me to help with the community. I'm checking everything what is doing, step by step. Most my code was written by GLM-5.2

@gonzoblasco gonzoblasco deleted the fix/7787-loader-deps-search-serializer branch July 15, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(router-core): use configured search serializer for loader dependency keys

3 participants