Skip to content

Comments

fix: resolve pending state when throwing notFound in beforeLoad#6654

Merged
schiller-manuel merged 1 commit intomainfrom
fix-6021
Feb 14, 2026
Merged

fix: resolve pending state when throwing notFound in beforeLoad#6654
schiller-manuel merged 1 commit intomainfrom
fix-6021

Conversation

@schiller-manuel
Copy link
Contributor

@schiller-manuel schiller-manuel commented Feb 14, 2026

fixes #6021

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of notFound errors thrown during route's beforeLoad hook, enabling parent routes to properly handle the error when appropriate.
  • Tests

    • Expanded test coverage for notFound scenarios in beforeLoad with various pendingComponent and async loading configurations.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 14, 2026

📝 Walkthrough

Walkthrough

This PR fixes a bug where throwing notFound() in a child route's beforeLoad hook doesn't properly resolve the pending state of a parent route's pendingComponent. It adds comprehensive test coverage for notFound scenarios in beforeLoad and modifies the error handling logic to allow notFound errors to bubble up to parent routes by propagating a routerCode parameter through the error handling chain.

Changes

Cohort / File(s) Summary
Test Coverage for notFound in beforeLoad
packages/react-router/tests/router.test.tsx
Added 249 lines of new test cases covering various scenarios where a child route's beforeLoad throws notFound, interacting with parent routes that have pendingComponent and/or pendingMs. Tests verify router transitions to idle state with statusCode 404.
Error Handling & notFound Routing
packages/router-core/src/load-matches.ts
Modified internal error handling to accept optional routerCode parameter and conditionally skip the notFoundComponent invariant check when routerCode is BEFORE_LOAD and a parent route exists. Updated function signatures: _handleNotFound, handleRedirectAndNotFound, and handleSerialError to propagate routerCode through the error handling chain.

Sequence Diagram

sequenceDiagram
    participant Child as Child Route<br/>(beforeLoad)
    participant Handler as Error Handler<br/>(load-matches)
    participant Parent as Parent Route<br/>(pendingComponent)
    participant Router as Router State

    Child->>Child: Navigation triggered
    Router->>Router: State → pending
    Parent->>Parent: pendingComponent shown
    Child->>Child: beforeLoad executes
    Child->>Handler: notFound() thrown<br/>(routerCode: BEFORE_LOAD)
    Handler->>Handler: Check: routerCode is BEFORE_LOAD<br/>and parentRoute exists?
    Handler->>Handler: Skip invariant check<br/>(allow bubbling)
    Handler->>Parent: Pass error up to parent
    Parent->>Router: Render notFoundComponent
    Router->>Router: State → idle, statusCode: 404
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested labels

package: react-router, package: router-core

Poem

🐰 A child route threw notFound with care,
But pendingComponent lingered in the air—
Now routerCode whispers "let it rise,"
And parent catches error, state complies!
From pending to idle, 404 in sight,
The notFound component shines so bright! ✨

🚥 Pre-merge checks | ✅ 5 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (45 files):

⚔️ examples/react/start-bare/package.json (content)
⚔️ examples/react/start-basic-auth/package.json (content)
⚔️ examples/react/start-basic-authjs/package.json (content)
⚔️ examples/react/start-basic-cloudflare/package.json (content)
⚔️ examples/react/start-basic-react-query/package.json (content)
⚔️ examples/react/start-basic-rsc/package.json (content)
⚔️ examples/react/start-basic-static/package.json (content)
⚔️ examples/react/start-basic/package.json (content)
⚔️ examples/react/start-bun/package.json (content)
⚔️ examples/react/start-clerk-basic/package.json (content)
⚔️ examples/react/start-convex-trellaux/package.json (content)
⚔️ examples/react/start-counter/package.json (content)
⚔️ examples/react/start-i18n-paraglide/package.json (content)
⚔️ examples/react/start-large/package.json (content)
⚔️ examples/react/start-material-ui/package.json (content)
⚔️ examples/react/start-streaming-data-from-server-functions/package.json (content)
⚔️ examples/react/start-supabase-basic/package.json (content)
⚔️ examples/react/start-tailwind-v4/package.json (content)
⚔️ examples/react/start-trellaux/package.json (content)
⚔️ examples/react/start-workos/package.json (content)
⚔️ examples/solid/start-basic-auth/package.json (content)
⚔️ examples/solid/start-basic-authjs/package.json (content)
⚔️ examples/solid/start-basic-cloudflare/package.json (content)
⚔️ examples/solid/start-basic-netlify/package.json (content)
⚔️ examples/solid/start-basic-nitro/package.json (content)
⚔️ examples/solid/start-basic-solid-query/package.json (content)
⚔️ examples/solid/start-basic-static/package.json (content)
⚔️ examples/solid/start-basic/package.json (content)
⚔️ examples/solid/start-bun/package.json (content)
⚔️ examples/solid/start-convex-better-auth/package.json (content)
⚔️ examples/solid/start-counter/package.json (content)
⚔️ examples/solid/start-i18n-paraglide/package.json (content)
⚔️ examples/solid/start-large/package.json (content)
⚔️ examples/solid/start-streaming-data-from-server-functions/package.json (content)
⚔️ examples/solid/start-supabase-basic/package.json (content)
⚔️ examples/solid/start-tailwind-v4/package.json (content)
⚔️ packages/react-router/tests/router.test.tsx (content)
⚔️ packages/react-start/package.json (content)
⚔️ packages/router-core/src/load-matches.ts (content)
⚔️ packages/solid-start/package.json (content)
⚔️ packages/start-plugin-core/package.json (content)
⚔️ packages/start-plugin-core/src/prerender.ts (content)
⚔️ packages/start-plugin-core/tests/prerender-ssrf.test.ts (content)
⚔️ packages/start-static-server-functions/package.json (content)
⚔️ packages/vue-start/package.json (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
✅ 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 accurately summarizes the main fix: resolving pending state when notFound is thrown in beforeLoad, directly addressing issue #6021.
Linked Issues check ✅ Passed The code changes implement proper handling of notFound thrown in beforeLoad by allowing ancestor routes to handle the error, preventing the pending state from persisting, which directly fixes issue #6021.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the notFound/pending state interaction: test coverage, load-matches internal logic, and related parameter propagation.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-6021
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch fix-6021
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

No actionable comments were generated in the recent review. 🎉


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

@nx-cloud
Copy link

nx-cloud bot commented Feb 14, 2026

View your CI Pipeline Execution ↗ for commit 780ec44

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

☁️ Nx Cloud last updated this comment at 2026-02-14 00:29:07 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 14, 2026

More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: 780ec44

@schiller-manuel schiller-manuel merged commit 2148b1b into main Feb 14, 2026
6 checks passed
@schiller-manuel schiller-manuel deleted the fix-6021 branch February 14, 2026 00:44
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.

Throwing notFound in beforeLoad does not resolve pending state

1 participant