Design
Error States:
Designing for Failure
Most design systems are designed for success. Error states are afterthoughts — vague, blame-shifting, and unhelpful. The gap between a product that frustrates and one that earns trust often lives precisely here.
The Three Failure States
Empty State
No data yet — first visit, search returns nothing, filtered list is empty. The user isn't in an error; they're in a starting point. The design should orient, not apologize.
Loading State
Content is coming. The user needs to know the system is working and roughly how long to wait. Skeleton screens > spinners for content-heavy layouts.
Error State
Something went wrong. The user needs to know what, whether it's their fault or the system's, and what to do next. This is the hardest and most neglected.
The Anatomy of a Bad Error Message
The pattern in all these: the message describes the symptom from the system's perspective ("an error occurred") without giving the user any actionable information. It's the equivalent of a doctor saying "something is wrong with you" and leaving the room.
The Anatomy of a Good Error Message
A good error message answers three questions: what happened, whose fault is it (system or user), and what do I do now?
Blame Attribution Matters
The tone of an error message should reflect who is at fault. System errors (server down, API timeout, unexpected failure) should be apologetic and own the problem. User errors (wrong password, invalid email, missing required field) should be clear and neutral — not apologetic (which confuses), not accusatory (which offends).
The worst pattern: blaming the user for a system error. "You've entered an invalid state" when the backend crashed. The user has done nothing wrong and now feels confused and at fault. This destroys trust disproportionately — the user remembers being blamed, not the specifics of what failed.
Empty States as Onboarding
The empty state is the most underused real estate in any product. When a user sees an empty list, empty dashboard, or empty search result, they are at maximum uncertainty about what to do next. This is not an edge case to minimize — it's often the first experience of a feature.
An effective empty state: explains why it's empty, shows what it will look like when full (a ghost preview or illustration of the populated state), and provides a single clear action to fill it. The empty state should make starting feel trivial — not daunting.
The Recovery Action Is Non-Negotiable
Every error state must include a recovery path. "Retry," "Go back," "Contact support," "Try a different file" — the specific action depends on the error, but the principle is absolute: never leave the user in a dead end.
In practice, this means error state components need a slot for a custom action, not just a static message. The action changes based on context: a network error gets "Retry," a permission error gets "Request access," a not-found error gets "Go home." One generic error component with a dynamic action slot handles all of these without duplication.