How to Design Error States Users Can Recover From

“Something went wrong” describes the product team’s knowledge, not the user’s problem.

How to Design Error States Users Can Recover From — Troiana insight cover

In short

A useful error state identifies what failed, preserves whatever the user has already done, and offers a specific recovery action. Design errors by cause and scope—field, action, section, page, or system—and never rely on colour or technical codes alone.

Name the failed action

An error message should start from the thing the person was trying to do: save a draft, invite a teammate, upload a file, complete payment, or load a report.

"Upload failed" is more useful than "Error 413." "We couldn't save your changes" is more useful than "Request unsuccessful." The technical detail may belong in logs or an expandable diagnostic panel, but it should not replace the product explanation.

Specific language also makes support easier. A person can report that an invitation failed; they cannot do much with an unexplained red banner.

Match the message to the scope

Put the error where its cause and remedy live.

  • Field error: next to the field, naming the requirement and how to satisfy it.
  • Action error: near the button or control that triggered the action.
  • Section error: inside the panel or component that could not load.
  • Page error: when the primary task on the page is unavailable.
  • System error: when several parts of the product are affected.

A global toast is a poor home for a form error because it disappears while the invalid field remains. A full-page error is excessive when one chart failed and the rest of the dashboard still works.

Say what can happen next

Every recoverable error needs a recovery action. Retry, edit, reconnect, remove the unsupported file, request access, choose another payment method, or contact support with a reference number.

Avoid telling people to "try again" when repeating the same action cannot change the outcome. If a file type is unsupported, list the accepted types. If the account lacks permission, identify who can grant it. If the service is temporarily unavailable, say that their work is safe and make retry possible without starting over.

The recovery action should be as close to the message as the failed action was.

Preserve work by default

An error becomes much worse when it destroys effort.

Keep form values after validation fails. Keep an upload in the queue if only one part failed. Save long drafts locally when the connection drops. Prevent duplicate payment or submission attempts when a retry is uncertain.

The interface should distinguish between "the operation definitely failed" and "we do not yet know whether it completed." The second case may require checking status before retrying, especially for payments, bookings, messages, and other actions that must not happen twice.

Design for accessibility

Colour can reinforce an error but cannot carry it alone. Identify the error in text, associate field-level messages with their controls, and move focus or announce updates when errors appear dynamically.

For a form with several errors, provide a summary that links to each affected field as well as inline guidance beside the fields themselves. This gives keyboard and screen-reader users a fast overview without making everyone hunt through the page.

Write the fix, not only the rule. "Password is invalid" names a problem. "Use at least 12 characters" gives someone a way through it.

Keep diagnostics without making users decode them

Support teams need timestamps, request IDs, affected services, and technical causes. Users need a comprehensible next step. A good error system serves both audiences without confusing them.

Show a short reference code when it will genuinely help support find the event. Keep the underlying exception, request context, and stack trace in secure logs. Never expose secrets, internal paths, raw database errors, or implementation details merely because they are available.

Test errors as real states

Do not review error copy in a spreadsheet alone. Render it inside the actual interface with long translations, narrow screens, keyboard navigation, slow responses, repeated failures, and partially loaded data.

Test what happens after recovery too. Does retry duplicate the action? Does correcting one field erase another? Does a dismissed message return if the problem remains? An error state is a flow, not a sentence.

Primary references

Common questions

Should error messages apologise?

An apology can be appropriate when the product caused a meaningful interruption, but it should not replace the explanation or recovery action. "Sorry" without help is still a dead end.

Should errors use technical codes?

Use a short reference code only when it helps support locate a logged event. Do not make the code the primary message or expect users to interpret HTTP status codes.

When should a product retry automatically?

Retry safe, temporary failures when repeating the operation cannot create a duplicate or unintended side effect. For consequential actions, confirm the previous attempt's status before retrying.

Have something worth building right?