Couldn't load vendor risk profile
The data feed returned an error. Try again, or talk to a human via the Comms corner.
Your go-to fallback family. Three content scopes — page, section, item — pair with <ErrorBoundary> to replace failed sub-trees. The fourth scope, chrome, isn't rendered here — each chrome pattern owns its own degraded shape.
This page is the one-stop shop: when each scope kicks in, what your user sees, and what each one lets them do. The placement principle lives in /error-handling; the React mechanism lives in /error-boundary; both live side by side here.
Triggered when a route's render throws. SiteLayout's baked-in boundary catches it. Takes the entire ContentWell so the user knows the page they wanted isn't reachable; AppBar + Preferences + Comms stay present (outside the boundary) so they can navigate elsewhere or report it.
<ErrorBoundary fallback={<ErrorState scope="page" />}>
{routeChildren}
</ErrorBoundary>Triggered when a region inside content throws. Caught by a consumer-placed boundary around the region. A card-sized inline error in the critical Card variant — its solid critical fill makes the failure pop at a glance without taking over the page.
The data feed returned an error. Try again, or talk to a human via the Comms corner.
<ErrorBoundary
fallback={
<ErrorState
scope="section"
title="Couldn't load vendor risk profile"
onReset={refetch}
/>
}
>
<RiskProfileWidget vendorId={vendor.id} />
</ErrorBoundary>Triggered when a single row / cell / list item throws. Caught by a per-item boundary so the rest of the list keeps rendering. Tiny inline placeholder with click-to-retry semantics.
A list with one failed row:
Vendor — Stripe
Vendor — Twilio
Vendor row unavailableVendor — Datadog
{vendors.map((v) => (
<ErrorBoundary
key={v.id}
fallback={<ErrorState scope="item" title="Vendor row unavailable" />}
>
<VendorRow vendor={v} />
</ErrorBoundary>
))}Each chrome pattern owns its own broken-state look because the shapes just don't match — an avatar circle, a brand anchor, and a corner button have nothing visual in common. The ground rules hold everywhere: keep the layout in place, keep the fallback quiet, add a tooltip hint, and (for Comms specifically) keep the transport working.
page | section | itemREQUIRED Which content scope. The chrome scope isn't a value here — chrome fallbacks live in each chrome pattern.
stringOverride the default title. Defaults vary by scope (e.g. page → "This page hit an error").
ReactNodeOverride the default body. Defaults explain "the rest still works."
ErrorThe captured Error. Rendered inside a <details> for technical detail. Wire from the ErrorBoundary render-prop.
() => voidRecovery affordance. Page scope defaults to window.location.reload() when absent.
stringOverride the recovery action label. Defaults: page → "Reload page", section → "Try again", item → "Retry".
onError callback that ships to Sentry. The user-facing fallback is one thing; the developer report is another.