Match the error type to its surface. A validation error belongs inline under the field, a lost connection reads as a banner or toast, and a server crash or permission block needs its own prominent space — each type has a natural home.
Let severity drive the surface. Minor issues stay inline, transient ones surface as a toast, and blocking failures earn a modal. The more an error interrupts the user, the more space it should occupy — and the reverse.
Every error needs an exit. A dead-end 'OK' button leaves people stuck. Give a real way out — a Retry, a link to support, or expandable technical details for those who want to dig in.
Write copy for humans, not machines. 'Error 500 — An error occurred' tells the user nothing. Say what broke, why, and what to do next in plain, specific language.
Prevent errors before they happen. Live inline validation — checking each rule as the user types and turning criteria green — stops most mistakes before submit. Validating only on submit just tells people they failed after the fact.
Keep field-level validation small, inline, and specific — anchored to the input it describes, not floating in a generic alert.
Do / Don't
Do: Offer a clear recovery action on every error — retry, undo, or a path to help.
Do: Match the surface to severity: inline for field errors, toast for transient issues, modal for true blockers.
Do: Validate inline as the user types so problems surface before submit.
Don't: Ship dead-end errors whose only option is 'OK'.
Don't: Surface raw codes like 'Error 500' or 'An error occurred' with no guidance.
Don't: Interrupt a minor validation slip with a full-screen modal.
The Design System Blueprint
An 11-page visual guide to consistent, scalable UI: colors, typography, spacing, components, motion.