Skip to content
Protocore Design Systemv1.6.9

/// Feedback

ErrorState

A centered failure panel with a danger accent rule, optional debugId tag and a retry affordance.

import { ErrorState } from "@protocore/pds";
View as Markdown

Basics

A title and detail under an ERROR eyebrow. Both default sensibly, so the smallest useful ErrorState is nearly propless.

Retry and debugId

Pass onRetry to render a retry button, and a debugId to surface the request/trace id as a mono metadata tag — the string support will ask for.

The five-state doctrine

ErrorState is state 3 of the five — *loading, empty, error, pending, data*. It means the request failed. Two rules keep it honest:

1. Always offer a way forward. Wire onRetry for anything transient; a dead end with no retry is the most common error-handling drift. 2. Always carry a `debugId`. The request id, trace id, or correlation id turns "it's broken" into a searchable support ticket.

Don't confuse this with empty — a fetch that succeeds with zero rows is an EmptyState, and dressing a failure as "No data" hides the problem from the user *and* your logs.

ErrorState vs. Banner vs. Toast

Pick by scope and blast radius:

  • ErrorState — the whole panel/view has no content to show because loading it failed. It *replaces* the content.
  • [Banner](/feedback/banner) — the surface still works, but there's a persistent, page-level problem to flag (degraded region, expired token).
  • [Toast](/feedback/toast) — a transient failure of a discrete action ("Couldn't save") that doesn't block the rest of the view.

Usage

Do

  • Wire onRetry for anything that might succeed on a second attempt.
  • Always surface a debugId so failures are traceable.
  • Write a plain-language title; put the technical cause in detail.
  • Use it when loading the surface failed and there's nothing to show.

Don't

  • Leave a failed surface with no retry and no id — a silent dead end.
  • Dump a raw stack trace or HTTP status as the title.
  • Use ErrorState for a transient action failure — that's a Toast.
  • Show "No data" (EmptyState) when the request actually errored.

Accessibility

KeysAction
TabMoves focus to the retry button when one is rendered.
Enter / SpaceActivates the focused retry button.
  • The root is `role="alert"`, so its content is announced assertively when it appears.
  • The `icon` slot is decorative (`aria-hidden`); the message lives in the title and detail.
  • The `debugId` renders as visible mono text, so it can be read aloud and copied — not hidden in an attribute.
  • The retry control is a real `<button>` with full keyboard and focus-ring support.

ErrorState props

PropTypeDefaultDescription
classNamestring
debugIdstringMachine debug identifier, rendered as a mono metadata tag.
detailReactNodeSecondary explanatory copy.
eyebrowReactNodeERRORMono uppercase eyebrow above the title.
iconReactNodeOptional decorative icon slot, rendered above the eyebrow.
onRetry(() => void)When provided, renders a retry button that calls this handler.
retryLabelstringRetryLabel for the retry button.
styleCSSProperties
titleReactNodeSomething went wrongSentence-case headline.

Related

  • EmptyStateA centered, dashed-frame placeholder for a surface that legitimately has nothing to show.
  • LoadingSkeletonShimmering placeholder blocks that hold a layout while its real content loads.
  • BannerA full-width tinted notice band for page- or section-level status, with optional action and dismiss.