fix(router-core): handle AbortError in router execution flow
fixes #4517
Summary by CodeRabbit
-
Bug Fixes
- Prevents error screens when a loader is aborted (AbortError). The app now continues rendering the intended content, applies head updates, and respects base paths on initial load.
- Reduces unnecessary error flashes during canceled navigations.
-
Tests
- Added tests validating AbortError handling on initial load with a base path for React and Solid routers.
- Minor test update adjusting className order to stabilize assertions.
🤖 Nx Cloud AI Fix Eligible
An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.
To disable these notifications, a workspace admin can disable them in workspace settings.
View your CI Pipeline Execution ↗ for commit 4f872078a6dcc280eaea31e28fbf42f184b076f6
| Command | Status | Duration | Result |
|---|---|---|---|
nx affected --targets=test:eslint,test:unit,tes... |
❌ Failed | 9m 10s | View ↗ |
nx run-many --target=build --exclude=examples/*... |
✅ Succeeded | 1m 44s | View ↗ |
☁️ Nx Cloud last updated this comment at 2025-12-23 14:32:15 UTC
More templates
- tanstack-router-react-example-authenticated-routes
- tanstack-router-react-example-authenticated-routes-firebase
- tanstack-router-react-example-basic
- tanstack-router-react-example-basic-default-search-params
- tanstack-router-react-example-basic-devtools-panel
- tanstack-router-react-example-basic-file-based
- tanstack-router-react-example-basic-non-nested-devtools
- tanstack-router-react-example-react-query
- tanstack-router-react-example-basic-react-query-file-based
- tanstack-router-react-example-basic-ssr-file-based
- tanstack-router-react-example-basic-ssr-streaming-file-based
- tanstack-router-react-example-basic-virtual-file-based
- tanstack-router-react-example-basic-virtual-inside-file-based
- tanstack-router-react-example-deferred-data
- tanstack-router-i18n-paraglide
- tanstack-router-react-example-kitchen-sink
- tanstack-router-react-example-kitchen-sink-file-based
- tanstack-router-react-example-kitchen-sink-react-query
- tanstack-router-react-example-kitchen-sink-react-query-file-based
- tanstack-router-react-example-large-file-based
- tanstack-router-react-example-location-masking
- tanstack-router-react-example-navigation-blocking
- tanstack-router-react-example-quickstart
- tanstack-router-react-example-quickstart-esbuild-file-based
- tanstack-router-react-example-quickstart-file-based
- tanstack-router-react-example-quickstart-rspack-file-based
- tanstack-router-react-example-quickstart-webpack-file-based
- router-monorepo-react-query
- router-mono-simple
- router-mono-simple-lazy
- tanstack-router-react-example-scroll-restoration
- tanstack-search-validator-adapters
- tanstack-start-example-bare
- tanstack-start-example-basic
- tanstack-start-example-basic-auth
- tanstack-router-react-example-basic-authjs
- tanstack-start-example-basic-cloudflare
- tanstack-start-example-basic-react-query
- tanstack-start-example-basic-rsc
- tanstack-start-example-basic-static
- tanstack-start-bun-hosting
- tanstack-start-example-clerk-basic
- tanstack-start-example-convex-trellaux
- tanstack-start-example-counter
- tanstack-start-i18n-paraglide
- tanstack-start-example-large
- tanstack-start-example-material-ui
- tanstack-start-streaming-data-from-server-functions
- tanstack-start-example-supabase-basic
- tanstack-start-tailwind-v4
- tanstack-start-example-trellaux
- tanstack-start-example-workos
- tanstack-router-react-example-view-transitions
- tanstack-router-react-example-with-framer-motion
- tanstack-router-react-example-with-trpc
- tanstack-router-react-example-with-trpc-react-query
- tanstack-router-vue-example-basic-jsx
- tanstack-router-vue-example-basic-file-based-jsx
- tanstack-router-vue-example-basic-file-based-sfc
- tanstack-router-solid-example-authenticated-routes
- tanstack-router-solid-example-authenticated-routes-firebase
- tanstack-router-solid-example-basic
- tanstack-router-solid-example-basic-default-search-params
- tanstack-router-solid-example-basic-devtools-panel
- tanstack-router-solid-example-basic-file-based
- tanstack-router-solid-example-basic-non-nested-devtools
- tanstack-router-solid-example-basic-solid-query
- tanstack-router-solid-example-basic-solid-query-file-based
- tanstack-router-solid-example-basic-ssr-file-based
- tanstack-router-solid-example-basic-ssr-streaming-file-based
- tanstack-router-solid-example-basic-virtual-file-based
- tanstack-router-solid-example-basic-virtual-inside-file-based
- tanstack-router-solid-example-deferred-data
- tanstack-router-solid-i18n-paraglide
- tanstack-router-solid-example-kitchen-sink
- tanstack-router-solid-example-kitchen-sink-file-based
- tanstack-router-solid-example-kitchen-sink-solid-query
- tanstack-router-solid-example-kitchen-sink-solid-query-file-based
- tanstack-router-solid-example-large-file-based
- tanstack-router-solid-example-location-masking
- tanstack-router-solid-example-navigation-blocking
- tanstack-router-solid-example-quickstart
- tanstack-router-solid-example-quickstart-esbuild-file-based
- tanstack-router-solid-example-quickstart-file-based
- tanstack-router-solid-example-quickstart-rspack-file-based
- tanstack-router-solid-example-quickstart-webpack-file-based
- @tanstack/router-solid-mono-simple
- router-solid-mono-simple-lazy
- router-solid-monorepo-solid-query
- tanstack-router-solid-example-scroll-restoration
- tanstack-solid-router-search-validator-adapters
- tanstack-solid-start-example-basic
- tanstack-solid-start-example-basic-auth
- tanstack-solid-start-example-basic-authjs
- tanstack-solid-start-example-basic-cloudflare
- tanstack-solid-start-example-basic-netlify
- tanstack-solid-start-example-basic-nitro
- tanstack-start-example-basic-solid-query
- tanstack-solid-start-example-basic-static
- tanstack-solid-start-bun-hosting
- tanstack-solid-start-example-convex-better-auth
- tanstack-solid-start-example-counter
- tanstack-solid-start-i18n-paraglide
- tanstack-solid-start-example-large
- tanstack-solid-start-streaming-data-from-server-functions
- tanstack-solid-start-example-supabase-basic
- tanstack-solid-start-tailwind-v4
- tanstack-router-solid-example-view-transitions
- tanstack-router-solid-example-with-framer-motion
- tanstack-router-solid-example-with-trpc
@tanstack/arktype-adapter
npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@4570
@tanstack/directive-functions-plugin
npm i https://pkg.pr.new/TanStack/router/@tanstack/directive-functions-plugin@4570
@tanstack/eslint-plugin-router
npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@4570
@tanstack/history
npm i https://pkg.pr.new/TanStack/router/@tanstack/history@4570
@tanstack/nitro-v2-vite-plugin
npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@4570
@tanstack/react-router
npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@4570
@tanstack/react-router-devtools
npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@4570
@tanstack/react-router-ssr-query
npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@4570
@tanstack/react-start
npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@4570
@tanstack/react-start-client
npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@4570
@tanstack/react-start-server
npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@4570
@tanstack/router-cli
npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@4570
@tanstack/router-core
npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@4570
@tanstack/router-devtools
npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@4570
@tanstack/router-devtools-core
npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@4570
@tanstack/router-generator
npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@4570
@tanstack/router-plugin
npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@4570
@tanstack/router-ssr-query-core
npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@4570
@tanstack/router-utils
npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@4570
@tanstack/router-vite-plugin
npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@4570
@tanstack/server-functions-plugin
npm i https://pkg.pr.new/TanStack/router/@tanstack/server-functions-plugin@4570
@tanstack/solid-router
npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@4570
@tanstack/solid-router-devtools
npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@4570
@tanstack/solid-router-ssr-query
npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@4570
@tanstack/solid-start
npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@4570
@tanstack/solid-start-client
npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@4570
@tanstack/solid-start-server
npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@4570
@tanstack/start-client-core
npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@4570
@tanstack/start-fn-stubs
npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@4570
@tanstack/start-plugin-core
npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@4570
@tanstack/start-server-core
npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@4570
@tanstack/start-static-server-functions
npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@4570
@tanstack/start-storage-context
npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@4570
@tanstack/valibot-adapter
npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@4570
@tanstack/virtual-file-routes
npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@4570
@tanstack/vue-router
npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router@4570
@tanstack/vue-router-devtools
npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-devtools@4570
@tanstack/vue-router-ssr-query
npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-ssr-query@4570
@tanstack/vue-start
npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@4570
@tanstack/vue-start-client
npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@4570
@tanstack/vue-start-server
npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@4570
@tanstack/zod-adapter
npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@4570
commit: 4f87207
@SeanCassiere
Would there be a chance for us to have a conversation about this?
Sorry about that!
@schiller-manuel there were recent changes this flow if I'm not mistaken with the selective SSR stuff. Would this be an issue?
@leesb971204 provided Manuel's fine with these changes, I don't see a reason not to get this pushed in.
Edit: Also, please make sure that your test are reflected in
@tanstack/solid-routeras well.
Thanks for the comment! I’ve added the same test to solid-router as well.
Sorry about that!
@schiller-manuel there were recent changes this flow if I'm not mistaken with the selective SSR stuff. Would this be an issue?
@leesb971204 provided Manuel's fine with these changes, I don't see a reason not to get this pushed in.
Edit: Also, please make sure that your test are reflected in
@tanstack/solid-routeras well.
Are there any other tasks that need to be completed before this work can be approved?
Are there any other tasks that need to be completed before this work can be approved?
Other than the current merge conflict, as mentioned here, I'd like @schiller-manuel to take a look at how this is being handled.
Is there any particular reason this work hasn’t been reviewed yet?
no, we are just busy with a lot of stuff, sorry. will get back to you as soon as time permits
Walkthrough
Adds AbortError handling in loader error flow to prevent error propagation on initial load with basepath. Executes head, preserves/updates match status, and returns early. Adds React and Solid tests reproducing AbortError during basepath mount and asserting no error UI and correct path.
Changes
| Cohort / File(s) | Summary |
|---|---|
Core loader error handlingpackages/router-core/src/load-matches.ts |
Intercepts DOMException with name "AbortError" during loader errors; runs executeHead, merges head result, preserves prior pending status as success, and exits without triggering error handling. |
React tests for AbortError + basepathpackages/react-router/tests/loaders.test.tsx |
Adds test for loader rejecting with AbortError on initial load with basepath; asserts index renders, error UI absent, and path includes basepath. Minor className order change in a reproducer div. |
Solid tests for AbortError + basepathpackages/solid-router/tests/loaders.test.tsx |
Adds analogous test verifying AbortError on initial load with basepath does not render error component and basepath is preserved. |
Sequence Diagram(s)
sequenceDiagram
autonumber
actor User
participant App
participant Router
participant RouteLoader as Loader
participant Head as executeHead
participant UI as ErrorBoundary
User->>App: Open "/"
App->>Router: Initialize with basepath "/app"
Router->>Loader: Run loader (initial load)
note right of Loader: Abort due to basepath redirect
Loader-->>Router: Throw DOMException(name="AbortError")
alt AbortError
Router->>Head: executeHead()
Head-->>Router: headResult
note over Router: Merge head, preserve/resolve match status
Router-->>App: Render route content (no error)
App-->>User: UI shows index under "/app"
else Other errors
Router->>UI: Propagate to error boundary
UI-->>User: Error UI
end
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
- TanStack/router#4961 — Adjusts loader/error/executeHead interplay in router-core, touching the same loadMatches error pathway.
Suggested reviewers
- schiller-manuel
Poem
A hop, a skip, the loaders race—
Abort! says basepath, shifting place.
No burrowed error, calm instead,
We nibble greens while running head.
The trail now starts at “/app”, hooray—
A rabbit routes the tidy way. 🐇✨
Pre-merge checks and finishing touches
✅ 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(router-core): handle AbortError in router execution flow" succinctly and accurately describes the primary change (special-casing AbortError handling in router-core) and aligns with the modified files and added tests that target loader abort behavior; it is specific, concise, and relevant to the changeset. |
| Linked Issues Check | ✅ Passed | The changes directly address issue #4517 by adding special handling for DOMException 'AbortError' in packages/router-core/src/load-matches.ts to prevent the AbortError from bubbling into the ErrorBoundary, and by adding tests in react-router and solid-router that reproduce the basepath initial-load abort scenario and assert the app renders without showing the error route. These code and test updates match the linked issue's objective to avoid treating an unreasoned abort as an application error. |
| Out of Scope Changes Check | ✅ Passed | All modifications are limited to router-core logic and router-specific tests (react-router and solid-router) that validate the abort behavior; there are no changes to public/exported APIs or unrelated packages in the provided summary. |
| Docstring Coverage | ✅ Passed | No functions found in the changes. Docstring coverage check skipped. |
✨ Finishing touches
- [ ] 📝 Generate Docstrings
🧪 Generate unit tests
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Comment @coderabbitai help to get the list of available commands and usage tips.
The tests can only pass after #5202 has been merged.
any update please?