Skip to content

Conversation

@Ju-MINJAE
Copy link

@Ju-MINJAE Ju-MINJAE commented Jan 10, 2026

Description

Fixes #6310

I investigated the issue using the reproduction repository provided in the issue.
Currently, buildLocation attempts to execute stringify even when params.parse fails or throws an error. In SSR environments, this causes the server to throw a 500 error (crash) instead of rendering the NotFound boundary.

Proposed Solution

I wrapped the stringify execution in a try-catch block within buildLocation.
If stringification fails, it now silently ignores the error. This prevents the app from crashing and allows the router to render the NotFound component correctly.

Before:
before

After:
after

Summary by CodeRabbit

  • Bug Fixes
    • Improved router stability by implementing graceful error handling for parameter serialization. Navigation will no longer fail unexpectedly due to serialization errors.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 10, 2026

📝 Walkthrough

Walkthrough

The buildLocation function in the router core now wraps the stringifyParams function call with a try-catch block. When stringify throws an error, it's caught and silently ignored, preventing navigation failures caused by stringify errors during parameter processing.

Changes

Cohort / File(s) Summary
Parameter Stringify Error Handling
packages/router-core/src/router.ts
Added try-catch wrapper around stringifyParams function call in buildLocation to gracefully handle stringify errors without interrupting navigation

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

  • #4981: Both PRs modify buildLocation's param stringification logic with error handling around stringifyParams calls

Suggested labels

package: router-core

Suggested reviewers

  • schiller-manuel

Poem

🐰 A hop and a skip through routing roads,
When stringify stumbles with heavy loads,
We catch the error, let it rest,
Navigation flows on, passing the test! ✨

🚥 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 'fix: prevent crash in buildLocation when params stringification fails' directly describes the main change: wrapping stringify in try-catch to prevent crashes.
Linked Issues check ✅ Passed The PR addresses issue #6310 by wrapping stringify in try-catch to prevent crashes when stringification fails, matching the desired outcome to handle stringify failures gracefully.
Out of Scope Changes check ✅ Passed All changes are scoped to buildLocation's param handling and directly address the crash prevention requirement from issue #6310.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

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 1704-1708: The empty catch swallowing errors in the try around
Object.assign(nextParams, fn(nextParams)) hides stringify failures; update the
catch to log the error (including the error object and relevant context such as
nextParams and fn.name or a stringified fn) so developers can debug, using the
router's existing logger if available (e.g., this.logger or a module logger) or
fallback to console.error, and guard the log behind a development check (e.g.,
process.env.NODE_ENV !== 'production' or an existing debug flag) so production
noise is avoided.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7cd1f82 and 2bc3dd7.

📒 Files selected for processing (1)
  • packages/router-core/src/router.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety for all code

Files:

  • packages/router-core/src/router.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Implement ESLint rules for router best practices using the ESLint plugin router

Files:

  • packages/router-core/src/router.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.
📚 Learning: 2025-10-01T18:30:26.591Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.

Applied to files:

  • packages/router-core/src/router.ts
📚 Learning: 2025-12-17T02:17:55.086Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6120
File: packages/router-generator/src/generator.ts:654-657
Timestamp: 2025-12-17T02:17:55.086Z
Learning: In `packages/router-generator/src/generator.ts`, pathless_layout routes must receive a `path` property when they have a `cleanedPath`, even though they are non-path routes. This is necessary because child routes inherit the path from their parent, and without this property, child routes would not have the correct full path at runtime.

Applied to files:

  • packages/router-core/src/router.ts
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • packages/router-core/src/router.ts
📚 Learning: 2025-12-21T12:52:35.231Z
Learnt from: Sheraff
Repo: TanStack/router PR: 6171
File: packages/router-core/src/new-process-route-tree.ts:898-898
Timestamp: 2025-12-21T12:52:35.231Z
Learning: In `packages/router-core/src/new-process-route-tree.ts`, the matching logic intentionally allows paths without trailing slashes to match index routes with trailing slashes (e.g., `/a` can match `/a/` route), but not vice-versa (e.g., `/a/` cannot match `/a` layout route). This is implemented via the condition `!pathIsIndex || node.kind === SEGMENT_TYPE_INDEX` and is a deliberate design decision to provide better UX by being permissive with missing trailing slashes.

Applied to files:

  • packages/router-core/src/router.ts

Comment on lines +1704 to +1708
try {
Object.assign(nextParams, fn(nextParams))
} catch (err) {
//
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add logging for stringify failures to aid debugging.

While preventing crashes is the right approach for resilience, the empty catch block makes it difficult to diagnose when and why parameter stringification fails. This could hide bugs or configuration issues that developers need to be aware of.

Consider logging the error at least in development mode:

🔍 Proposed enhancement to add development logging
 try {
   Object.assign(nextParams, fn(nextParams))
 } catch (err) {
-  //
+  if (process.env.NODE_ENV !== 'production') {
+    console.warn(
+      `Failed to stringify params for route ${route.id}:`,
+      err,
+    )
+  }
 }

This maintains the crash prevention while providing visibility into stringify failures during development.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
Object.assign(nextParams, fn(nextParams))
} catch (err) {
//
}
try {
Object.assign(nextParams, fn(nextParams))
} catch (err) {
if (process.env.NODE_ENV !== 'production') {
console.warn(
`Failed to stringify params for route ${route.id}:`,
err,
)
}
}
🤖 Prompt for AI Agents
In @packages/router-core/src/router.ts around lines 1704 - 1708, The empty catch
swallowing errors in the try around Object.assign(nextParams, fn(nextParams))
hides stringify failures; update the catch to log the error (including the error
object and relevant context such as nextParams and fn.name or a stringified fn)
so developers can debug, using the router's existing logger if available (e.g.,
this.logger or a module logger) or fallback to console.error, and guard the log
behind a development check (e.g., process.env.NODE_ENV !== 'production' or an
existing debug flag) so production noise is avoided.

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.

Params parse/stringify behavior doesn't match types when narrowing params

1 participant