Skip to content

Components · Status and feedback

ErrorState

A region failed to load: what failed, why in plain words, and a retry.

@rookcom/monarch-reactComponent

Error with retry and request id

Usage examples

Forbidden and offline

Panel error boundary

Purpose

ErrorState says what failed to load in a list, panel or card and offers a retry. ErrorStateBoundary catches a render error in one panel and shows an ErrorState instead of breaking the page.

Use when

  • A list or panel failed to load (onRetry).
  • The person may not see a record (kind="forbidden"), or it no longer exists (kind="not-found").
  • A request never reached the server (kind="offline").
  • One pane of a multi-pane screen should fail on its own (ErrorStateBoundary).

Avoid when

  • There is simply no data: use EmptyState.
  • A whole route failed or is missing: use ErrorPage.
  • A small section failed inside a card that otherwise works: use InlineErrorRetry.
  • Content is still loading: use LoadingState.

Design principles

  • ErrorState is an EmptyState with a kind icon and a primary "Try again" button.
  • Plain language only. The product maps its errors to a kind (errorKindFromStatus helps) and writes the copy; never show a raw error message, stack or vendor name.
  • Retry is offered only when it can help: forbidden and not-found never render it.
  • The request id is there for support conversations: monospace, selectable and copyable.

API reference

import { ErrorState, ErrorStateBoundary, errorKindFromStatus, errorKindIcon } from '@rookcom/monarch-react';
ExportKindRenderingRoot class
ErrorStatecomponentserver-safe.mn-error-state
ErrorStateBoundarycomponentclient.mn-error-state
errorKindFromStatusutilityserver-safe–
errorKindIconutilityserver-safe–

ErrorState accepts every EmptyState prop except kind, icon and actions, which it redefines; the ref is forwarded to the root <div>.

errorKindFromStatus(status, { offline }) maps an HTTP status to a kind: 0 or offline → offline, 401/403 → forbidden, 404/410 → not-found, 5xx → server, anything else → error. maintenance is never inferred.

errorKindIcon(kind) returns the default decorative glyph for a kind, for products composing their own layout.

ErrorStateBoundary is a client component (React error boundary): fallback (node or ({ error, reset }) => node), onError, onReset and resetKeys; without fallback it renders ErrorState with the given title, description and a retry that resets it.

LoadingState moved to its own folder in 0.4 (loading-state); it is still exported from @rookcom/monarch-react with the same props and class names.

Generated from the TypeScript declarations of packages/react/src/components/feedback/error-state.

Properties

ErrorState

Something failed to load. Say what failed and offer a retry.

PropTypeDescription
title requiredReactNode
actionsReactNodeExtra actions next to retry.
childrenReactNodeExtra content after the actions, such as a list of next steps.
classNamestring
clearFiltersLabelstringLabel of the clear-filters button. Default "Clear filters".
descriptionReactNode
headingLevelEmptyStateHeadingLevelTitle element. Default `h3`. Match the page outline (no skipped levels); use `p` where a heading would be wrong, such as inside a table cell.
iconReactNodeReplaces the kind's default icon.
idstring
kindErrorKindWhat went wrong. Sets the default icon and whether retry is offered. Exposed as `data-kind`.
layout"stack" | "line"`stack` (default) centres icon, text and actions in a column; `line` is a single left-aligned row (icon, text, actions) for a list or dashboard section that has nothing in it.
onClearFilters(() => void)With `kind="filtered"`, renders a "Clear filters" button before any other actions. The product resets its own filters.
onRetry(() => void)Retry handler; renders a "Try again" button (not for `forbidden` or `not-found`).
requestIdstringThe request id from the failed response, shown in monospace with a copy button so the person can quote it to support.
requestIdLabelstringLabel before the request id. Default "Request ID".
retryingbooleanShows the retry button as busy while a retry is in flight.
retryLabelstring
size"inline" | "page" | "compact"`inline` (default) sits inside a card or table; `page` fills an empty view; `compact` is a tighter block for table bodies, side panels and small cards.
tipReactNodeA short hint under the actions, such as a keyboard shortcut (compose it with Kbd). Shown in small muted text.

ErrorStateBoundary

Error boundary for one panel or region: a render error inside it shows an ErrorState with "Try again" instead of taking down the page. The rest of the page keeps working.

PropTypeDescription
title requiredReactNode
childrenReactNode
descriptionReactNode
fallbackReactNode | ((props: ErrorStateBoundaryFallbackProps) => ReactNode)Replaces the default fallback (an ErrorState with a retry that resets the boundary). A function receives the error and `reset`.
headingLevelEmptyStateHeadingLevelTitle element. Default `h3`. Match the page outline (no skipped levels); use `p` where a heading would be wrong, such as inside a table cell.
onError((error: Error, info: ErrorInfo) => void)Report the error (logging, monitoring). Called once per caught error.
onReset(() => void)Called after the boundary resets, from the retry button or a `resetKeys` change.
requestIdstringThe request id from the failed response, shown in monospace with a copy button so the person can quote it to support.
requestIdLabelstringLabel before the request id. Default "Request ID".
resetKeysreadonly unknown[]When any value changes (by `Object.is`) while an error is shown, the boundary resets. Pass the inputs the failed panel depends on, such as the selected record id.
retryLabelstring
size"inline" | "page" | "compact"`inline` (default) sits inside a card or table; `page` fills an empty view; `compact` is a tighter block for table bodies, side panels and small cards.

Variants

PropValuesDescription
kind'error''forbidden''not-found''offline''server''maintenance'Sets the default icon and tint and whether retry is offered. Non-default kinds are exposed as data-kind.
size'inline''page''compact'From EmptyState. compact fits a side panel or table body.
retryLabel'string'Retry button text. Default "Try again".

States

StateExposed asBehaviour
Error with retry–A primary retry button is rendered when onRetry is set and the kind allows it, before any extra actions.
Retryingaria-busy="true" on the retry buttonretrying shows the Button loading state: a spinner, clicks blocked, focus kept on the button.
Forbidden / not founddata-kindNeutral icon tile, no retry button.
Offlinedata-kind="offline"Warning-tinted icon tile; retry stays available.

Interaction behaviour

  • The retry button calls onRetry; while retrying is true further clicks are ignored.
  • The request-id copy button copies the id and announces "Copied to clipboard".
  • ErrorStateBoundary: "Try again" clears the error and renders the children again; a change in resetKeys does the same.

Keyboard support

KeysAction
Tab / Shift+TabMoves through retry, extra actions and the copy button.
Enter / SpaceActivates the focused button.

Accessibility

Role
alert
Accessible name
–
  • ErrorState has role="alert", so it is announced when it appears.
  • The icon tile is aria-hidden; the title carries the meaning.
  • While retrying, the retry button stays focusable (aria-disabled + aria-busy), so keyboard users keep their place.
  • The copy button is named "Copy Request ID" (from requestIdLabel).
  • Verified with axe in jsdom and in Chromium, Firefox and WebKit on /components/error-state.

Responsive behaviour

  • Centred with a 28rem maximum width (from EmptyState); actions wrap.
  • Long request ids break anywhere instead of overflowing at 320px.

Theme support

  • The error and server icon tiles use the danger subtle and strong tokens; offline uses warning; forbidden, not-found and maintenance use the muted surface.
  • Colours are Monarch semantic tokens only, so light, dark and more-contrast themes apply automatically.

Do and don't

Do

  • Say what failed in the title.
  • Pass the request id when your API returns one.
  • Map statuses to kinds with errorKindFromStatus, then pick your own copy per kind.
  • Wrap independent panes in ErrorStateBoundary so one failure does not blank the screen.

Don't

  • Do not show raw error messages, codes or vendor names as the title.
  • Do not offer retry for a permission error.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsButton, CopyButton, EmptyState

Testing coverage

  • ErrorState is an alert and calls onRetry; retry renders before extra actions.
  • Default props keep the 0.3 markup (no data-kind).
  • forbidden and not-found hide retry; offline keeps it.
  • retrying keeps focus on the busy button and blocks repeat activation.
  • The request id renders as code with a named copy button.
  • errorKindFromStatus maps statuses and offline to kinds.
  • ErrorStateBoundary catches a render error without showing its message, calls onError, resets on retry and on resetKeys change, and accepts a render-prop fallback.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery; Cross-browser axe: /components/error-state

Tests: packages/react/src/components/feedback/error-state