Skip to content

Error State

What a screen shows when something failed — the screen most often left to whoever was implementing it at the time.

UI Components

An error state is what a screen shows when something failed. It is among the most-seen screens in any product and the least designed, because it gets built last, under deadline, by whoever was implementing the happy path.

The result is a genre of message that reports a failure and offers nothing: a red box, a code, occasionally an apology.

Three questions, in order

What failed? In plain language. "We could not reach the billing service", not "Error 4021".

Was anything lost? This is the question people actually have, and it is the one most often unanswered. Somebody who just spent ten minutes on a form wants to know whether the ten minutes are gone. Say so unprompted.

What now? A control, not an instruction. Retry, go back, contact support with a reference — as a button, not as a sentence telling them to find one.

Twelve words can do all three: We could not save your changes. Your work is still here. Try again.

The kinds, which need different treatments

Field-level. A single input failed validation. Beside the field, immediately, with the entry preserved. See form design.

Action-level. A save or a submit failed. Near the control that was pressed, with the option to retry.

Region-level. A panel or table could not load. In place of that region, not as a page-wide message — the rest of the screen still works.

Page-level. The record does not exist, or access is denied. A full screen, with a route somewhere useful rather than a dead end.

Global. The service is degraded. A banner, because it affects everything.

Using the wrong level is the common structural mistake: a page-wide message about one field, or a small inline note about a total outage.

Error is not empty

A failed request and an empty result are different situations, and conflating them is a specific, damaging bug.

Showing "No records yet" when the request failed tells a customer with nine thousand records that they have none. They may act on that. See empty state.

The two need distinct states, and the error version needs a retry — because unlike an empty result, this one might work on the second attempt.

Writing them

No blame. "You entered an invalid date" and "This date format is not recognised — try DD/MM/YYYY" describe the same event; one of them helps.

No jargon leaking from the stack. A constraint violation, a 422, a serialisation failure — these are internal facts, not user-facing ones.

Codes small, copyable, and secondary. They are for support, and support cannot help without them, so include them — underneath the explanation, not in place of it.

No false reassurance. "Something went wrong, please try again" said cheerfully after the third failure is worse than an honest statement that this is not working and here is how to reach someone.

The parts usually missing

Announcement. An error needs an assertive live region, so it interrupts. This is the one case where interrupting is right: a polite announcement queued behind other output means somebody keeps working against a failure they have not heard about.

Retry that is actually possible. A retry control that re-runs the same failed request with no backoff, on a service that is down, is a button that does nothing four times.

Preserved input. The single most expensive small defect in this area, and almost always an accident of how the failure path was built rather than a decision.

A route out of a dead end. A 404 with no navigation is a page somebody leaves the product from.

In practice

A long configuration form validates on submit. When the server rejects it, the page reloads with a red box at the top reading "Validation failed" and the form cleared.

Three problems compound. The person does not know which field was wrong. They do not know their ten minutes of typing is gone until they scroll. And the message tells them nothing they can act on.

The repair is not a better message. Field-level errors beside their fields, the entries preserved, and a summary at the top that links to each one. The validation rules did not change and neither did the failure rate.

What changed is that a failure stopped costing ten minutes.

Where teams get it wrong

  • Reporting the failure and nothing else. No route, no reassurance.
  • The empty state on a failed request. Telling somebody their data is gone.
  • Clearing the form. An accident of the failure path, paid for by the user.
  • Codes instead of explanations. Useful to support, useless to the reader.
  • Polite announcements. A failure somebody keeps working against.
  • The wrong level. A page-wide message about one field, or an inline note about an outage.

Frequently Asked Questions