Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/router/guide/not-found-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ There are 2 uses for not-found errors in TanStack Router:

- **Non-matching route paths**: When a path does not match any known route matching pattern **OR** when it partially matches a route, but with extra path segments
- The **router** will automatically throw a not-found error when a path does not match any known route matching pattern
- If the router's `notFoundMode` is set to `fuzzy`, the nearest parent route with a `notFoundComponent` will handle the error. If the router's `notFoundMode` is set to `root`, the root route will handle the error.
- If the router's `notFoundMode` is set to `fuzzy`, the nearest matching route with a `notFoundComponent` will handle the error. If the router's `notFoundMode` is set to `root`, the root route will handle the error.
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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the fuzzy mode selection logic in the router implementation

# Search for the findGlobalNotFoundRouteId function implementation
ast-grep --pattern $'function findGlobalNotFoundRouteId($$$) {
  $$$
}'

# Also search for how children property is used in route selection
rg -n -A5 -B3 'route\.children' --type=ts --glob='**/router-core/**'

Repository: TanStack/router

Length of output: 3830


🏁 Script executed:

cat -n docs/router/guide/not-found-errors.md

Repository: TanStack/router

Length of output: 15266


Document the actual selection criteria for fuzzy mode: routes must have children, not notFoundComponent.

The documentation on lines 13, 19, 37, 43, and 55-58 incorrectly describes how fuzzy mode selects which route handles a not-found error. The implementation (packages/router-core/src/router.ts:3163-3176) selects based on whether a route has children, not whether it has a configured notFoundComponent:

if (route.children) {  // ← Selection is based on children
  return route.id
}

The notFoundComponent (or defaultNotFoundComponent) is required to render something, but is not the criterion for route selection. The selection criteria should be: the nearest route with children (layout routes), not the presence of a notFoundComponent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/router/guide/not-found-errors.md` at line 13, Update the documentation
to reflect that in fuzzy not-found selection the router chooses the nearest
ancestor route that has children (i.e., a layout route), not one that merely
defines a notFoundComponent; change descriptions referencing `notFoundMode`,
`fuzzy`, `notFoundComponent`, and `defaultNotFoundComponent` to state the
selection criterion is presence of `children` on the route (match implementation
in router.ts where selection checks `if (route.children)`) and note that
`notFoundComponent`/`defaultNotFoundComponent` are only required for rendering,
not for selection.

- Examples:
- Attempting to access `/users` when there is no `/users` route
- Attempting to access `/posts/1/edit` when the route tree only handles `/posts/$postId`
- **Missing resources**: When a resource cannot be found, such as a post with a given ID or any asynchronous data that is not available or does not exist
- **You, the developer** must throw a not-found error when a resource cannot be found. This can be done in the `beforeLoad` or `loader` functions using the `notFound` utility.
- Will be handled by the nearest parent route with a `notFoundComponent` (when `notFound` is called within `loader`) or the root route.
- Will be handled by the nearest matching route with a `notFoundComponent` (when `notFound` is called within `loader`) or the root route.
- Examples:
- Attempting to access `/posts/1` when the post with ID 1 does not exist
- Attempting to access `/docs/path/to/document` when the document does not exist
Expand All @@ -34,13 +34,12 @@ Depending on the `notFoundMode` option, the router will handle these automatic e

### `notFoundMode: 'fuzzy'`

By default, the router's `notFoundMode` is set to `fuzzy`, which indicates that if a pathname doesn't match any known route, the router will attempt to use the closest matching route with children/(an outlet) and a configured not found component.
By default, the router's `notFoundMode` is set to `fuzzy`, which indicates that if a pathname doesn't match any known route, the router will attempt to use the closest matching route with a configured `notFoundComponent`.

> **❓ Why is this the default?** Fuzzy matching to preserve as much parent layout as possible for the user gives them more context to navigate to a useful location based on where they thought they would arrive.

The nearest suitable route is found using the following criteria:

- The route must have children and therefore an `Outlet` to render the `notFoundComponent`
- The route must have a `notFoundComponent` configured or the router must have a `defaultNotFoundComponent` configured
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.

⚠️ Potential issue | 🔴 Critical

Missing critical criterion: route must have children.

Based on the implementation (see comment on line 13), the criteria should include:

  • The route must have children (i.e., be a parent/layout route)
  • The route must have a notFoundComponent configured or the router must have a defaultNotFoundComponent configured
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/router/guide/not-found-errors.md` at line 43, Update the sentence to
include the missing criterion that the route must have children (i.e., be a
parent/layout route) in addition to having a notFoundComponent or the router
having a defaultNotFoundComponent; specifically revise the text referencing
`notFoundComponent` and `defaultNotFoundComponent` to read that the route must
have children and must have a `notFoundComponent` configured (or the router must
have a `defaultNotFoundComponent` configured).


For example, consider the following route tree:
Expand All @@ -53,9 +52,10 @@ If provided the path of `/posts/1/edit`, the following component structure will

- `<Root>`
- `<Posts>`
- `<Posts.notFoundComponent>`
- `<Post>`
- `<Post.notFoundComponent>`

The `notFoundComponent` of the `posts` route will be rendered because it is the **nearest suitable parent route with children (and therefore an outlet) and a `notFoundComponent` configured**.
The `notFoundComponent` of the `$postId` route will be rendered because it is the **nearest matching route with a `notFoundComponent` configured**.
Comment on lines +55 to +58
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.

⚠️ Potential issue | 🔴 Critical

Example contradicts the actual implementation behavior.

Given the route tree structure where posts has children but $postId does not, the actual implementation would select the posts route (the nearest route with children), not the $postId route.

The correct rendering for /posts/1/edit with fuzzy mode would be:

- <Root>
  - <Posts>
    - <Post>
      - <Posts.notFoundComponent>

The notFoundComponent of the posts route would be rendered because it is the nearest matching route with children (i.e., the nearest parent/layout route).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/router/guide/not-found-errors.md` around lines 55 - 58, The example text
incorrectly states that `<Post.notFoundComponent>` will render for
`/posts/1/edit` in fuzzy mode; update the wording and example to reflect that
the nearest parent route with children is chosen, so `<Posts.notFoundComponent>`
is rendered. Locate the section describing the `$postId` route behavior
(references to `$postId`, `<Post>`, `<Posts>`, `<Post.notFoundComponent>`, and
`<Posts.notFoundComponent>`), change the example tree and explanatory sentence
to show `<Posts.notFoundComponent>` as the rendered component, and adjust the
explanation to say the nearest matching route with children (the parent/layout
`posts` route) is used instead of the leaf `$postId` route.


### `notFoundMode: 'root'`

Expand Down
Loading