From acf710d80ceb98ff0dfbd58ea115b5b36053be7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Wed, 15 Jul 2026 09:43:46 +0200 Subject: [PATCH] Drop redundant bootstrap error boundary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit React Router routes render and loader errors to the route-level boundaries, so the App-level boundary above the router could only catch provider render failures — which today are trivial — while true bootstrap failures throw at module load before it mounts. Neither console nor trust wraps App this way. Rely on the root route boundary instead and remove the BootstrapError fallback it used. Signed-off-by: Émile Ré --- apps/compliance-portal/src/App.tsx | 10 ++--- .../src/components/errors/BootstrapError.tsx | 45 ------------------- .../src/components/errors/GlobalError.tsx | 2 +- contrib/claude/error-handling.md | 2 +- 4 files changed, 5 insertions(+), 54 deletions(-) delete mode 100644 apps/compliance-portal/src/components/errors/BootstrapError.tsx diff --git a/apps/compliance-portal/src/App.tsx b/apps/compliance-portal/src/App.tsx index f7f4e21dc..c8471e4e5 100644 --- a/apps/compliance-portal/src/App.tsx +++ b/apps/compliance-portal/src/App.tsx @@ -18,19 +18,15 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -import { ErrorBoundary } from "@probo/ui/src/v2/ErrorBoundary/ErrorBoundary"; import { RouterProvider } from "react-router"; -import { BootstrapError } from "#/components/errors/BootstrapError"; import { RelayProvider } from "#/lib/relay/RelayProvider"; import { router } from "#/routes"; export function App() { return ( - }> - - - - + + + ); } diff --git a/apps/compliance-portal/src/components/errors/BootstrapError.tsx b/apps/compliance-portal/src/components/errors/BootstrapError.tsx deleted file mode 100644 index 759d0527e..000000000 --- a/apps/compliance-portal/src/components/errors/BootstrapError.tsx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2026 Probo Inc . -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -import { Anchor } from "@probo/ui/src/v2/Button/Anchor"; -import { Button } from "@probo/ui/src/v2/Button/Button"; -import { ErrorState } from "@probo/ui/src/v2/ErrorState/ErrorState"; -import { useTranslation } from "react-i18next"; - -import { getPathPrefix } from "#/lib/http/pathPrefix"; - -// Outermost fallback for failures that happen before (or in) the router itself. -// It cannot use the router (no context yet), so navigation is a plain anchor and -// recovery is a hard reload. -export function BootstrapError() { - const { t } = useTranslation(); - - return ( - - - {t("errors.actions.backToTrustCenter")} - - - - )} - /> - ); -} diff --git a/apps/compliance-portal/src/components/errors/GlobalError.tsx b/apps/compliance-portal/src/components/errors/GlobalError.tsx index ecb266b91..3f813d3e2 100644 --- a/apps/compliance-portal/src/components/errors/GlobalError.tsx +++ b/apps/compliance-portal/src/components/errors/GlobalError.tsx @@ -61,7 +61,7 @@ interface GlobalErrorProps { } // Page-level error fallback: renders the v2 ErrorState with portal copy and -// actions. Used by the bootstrap boundary and the route boundaries. +// actions. Used by the route boundaries (root + page). export function GlobalError({ error, onRetry, fullPage = false }: GlobalErrorProps) { const { t } = useTranslation(); const { code, titleKey, descriptionKey } = resolveContent(error); diff --git a/contrib/claude/error-handling.md b/contrib/claude/error-handling.md index a117ff93e..910a4202c 100644 --- a/contrib/claude/error-handling.md +++ b/contrib/claude/error-handling.md @@ -211,7 +211,7 @@ The portal ships three fallback tiers, all backed by the same `ErrorBoundary`: | Tier | Placement | Fallback | |------|-----------|----------| -| Global (bootstrap) | around `RouterProvider` in `App.tsx`, and the root route | `ErrorState` full page (standalone) | +| Global | root route (`RootErrorBoundary`) | `ErrorState` full page (standalone) | | Page | pathless child route inside the layout | `ErrorState` inside the shell (TopBar/footer survive) | | Section / row | around a fragment-reading subtree | `InlineError` (vertical for sections, horizontal for rows) with a retry |