Skip to content
goodtabs UI
BrowseBrowse components

Error state

Says what went wrong and offers a single retry.

npx shadcn@latest add https://ui.goodtabs.co/r/error-state.json

With the @goodtabs namespace in components.json: npx shadcn@latest add @goodtabs/error-state

The smallest useful version.

With a reason

A description that changes after each retry.

Usage

import { ErrorState } from "@/components/ui/error-state"

<ErrorState title="Could not load deploys">
  <Button onClick={retry}>Try again</Button>
</ErrorState>

Props

PropTypeDefaultDescription
titlestringWhat went wrong, in plain words.
descriptionstringWhy it happened and what happens next.
childrenReactNodeThe one action, usually a retry button.

Source

error-state/error-state.tsx
import * as React from "react";
import { TriangleAlertIcon } from "lucide-react";
import { cn } from "@/lib/utils";

type ErrorStateProps = Omit<React.ComponentProps<"div">, "title"> & {
  /** What went wrong, in plain words. */
  title: string;
  /** Why, and what the person can expect. One or two sentences. */
  description?: string;
};

/**
 * What went wrong and one way forward. Pass a single retry button as the
 * children. It announces itself as an alert when it appears.
 */
export function ErrorState({ title, description, className, children, ...props }: ErrorStateProps) {
  return (
    <div
      role="alert"
      data-slot="error-state"
      className={cn("flex flex-col items-center gap-3 px-4 py-6 text-center", className)}
      {...props}
    >
      <span className="flex size-9 items-center justify-center rounded-full border bg-muted text-foreground">
        <TriangleAlertIcon className="size-4" aria-hidden="true" />
      </span>
      <div className="space-y-1">
        <h3 className="text-sm font-medium text-foreground">{title}</h3>
        {description && <p className="max-w-xs text-sm text-foreground/70">{description}</p>}
      </div>
      {children}
    </div>
  );
}

For AI agents

Hand your agent this page, the markdown at /components/error-state/prompt.md, or the Copy AI prompt button above.

When to use

  • A region failed to load and retrying can help
  • Replacing the content of a card, table or panel, not the whole page

When not to use

  • Field validation, which belongs next to the field
  • Errors the person cannot act on, where plain text is enough

Agent notes

  • Renders role=alert, so mount it when the error happens rather than hiding it
  • Stays monochrome on purpose: the icon and the words carry the meaning, not a red fill
  • Pass one action. Two buttons turn a retry into a decision
  • Add the border and radius through className when you place it inside a card