Error States That Help Instead of Frustrate
Errors are inevitable. Servers fail. Networks drop. Users make mistakes. The question isn't whether errors will happen - it's how your app responds when they do.
Bad error handling makes users feel stupid, frustrated, and likely to leave. Good error handling turns problems into moments of trust-building. "Yeah, that went wrong, but they helped me fix it" is a surprisingly positive experience.
Why Error Design Matters
When something breaks, users are already in a negative state. They were trying to do something and got blocked. How you communicate the error either adds to their frustration or alleviates it.
Poor error experiences:
- Destroy confidence in your product
- Make users feel blamed for the problem
- Waste their time figuring out what happened
- Lead to abandonment (they leave and don't come back)
Good error experiences:
- Acknowledge the problem clearly
- Explain in human terms what happened
- Offer a path forward
- Preserve any work the user has done
The difference is design. It's not harder to do it well. It just requires thinking about it.
Types of Errors
Different errors need different treatments.
Validation errors: User input doesn't meet requirements. Email format wrong, required field empty, password too short.
User errors: User tried something that isn't allowed. Deleting something that can't be deleted, accessing something they don't have permission for.
System errors: Something broke on your end. Server down, database failed, API timed out.
Network errors: Connection problems. Offline, slow connection, request timed out.
Not found errors: Requested resource doesn't exist. Dead link, deleted page, invalid URL.
Each category should be handled consistently, but differently from the others.
Writing Error Messages
Most error messages are terrible. "An error occurred." What error? "Invalid input." What's invalid? These tell users nothing.
Good error messages have three parts:
What happened: Describe the problem simply. "We couldn't save your changes" or "That email address isn't valid."
Why it happened (if it helps): Brief context when useful. "Our servers are having trouble right now" or "Email addresses need an @ symbol."
What to do about it: Give them a next step. "Please try again" or "Check the email and fix any typos" or "Refresh the page."
Keep the tone human and non-blaming. Not "You entered an invalid date" but "That date doesn't look right - try the format MM/DD/YYYY."
Avoid technical jargon. "Error 500" means nothing to most users. "Something went wrong on our end - we're looking into it" is actually helpful.
Form Validation Errors
Validation errors are the most common and the most frequently botched.
Show errors inline. Don't dump all errors at the top of the form. Put each error message directly below the field it relates to.
Validate as users go. Real-time validation catches problems before submit. Validate on blur (when leaving a field), not on every keystroke.
Mark the field visually. Red border, error icon, something that clearly indicates "this one has a problem."
Explain specifically. "Password must contain at least 8 characters, including a number" is actionable. "Invalid password" isn't.
Let them fix it easily. Keep the field editable, cursor positioned for correction. Don't make them click through hoops to get back to fixing the error.
Page-Level Error States
When an entire page fails to load or an action catastrophically fails, you need a full-screen error state.
Good 404 pages:
- Clear headline: "Page not found" (not "Error 404")
- Brief explanation: "The page you're looking for doesn't exist or was moved."
- Helpful options: Link to home, search box, popular pages
- Consistent with your design (not a default server page)
Good 500 pages:
- Honest acknowledgment: "Something went wrong on our end"
- Reassurance: "We've been notified and are working on it"
- Options: Refresh, go home, contact support
- Maybe some personality (a tasteful illustration, light humor if it fits your brand)
These pages should be static. They can't rely on your app working to render.
Handling Offline and Network Issues
Network errors deserve special treatment because they're not your fault or the user's.
Detect connection status. Show a banner: "You're offline. Changes will sync when you reconnect."
Queue actions when possible. Let users compose messages, create drafts, make changes locally. Sync when connection returns.
Retry intelligently. For failed requests, retry automatically a few times before showing an error. Include a manual "Retry" button.
Preserve their work. Nothing is worse than losing a long form entry to a network error. Save drafts locally. Auto-save frequently.
Error Prevention
The best error state is one the user never sees. Prevent errors where possible.
Disable invalid actions. Button for submitting a form? Gray it out until form is valid. Action that requires selection? Gray until something is selected.
Use constraints. Date picker instead of text field for dates. Dropdown instead of text for limited options. Remove the possibility of invalid input.
Provide defaults. Pre-fill sensible values. Less for users to get wrong.
Confirm destructive actions. "Are you sure you want to delete this?" with clear yes/no. Give them an out before the error becomes permanent.
Allow undo. Even better than confirmation: let them undo. "Message deleted. Undo" is faster and more forgiving than "Are you sure?" dialogs.
Visual Design of Errors
Errors should be visually distinct but not aggressive.
Color: Red is universal for errors, but don't rely on color alone (colorblind users). Combine with icons and text.
Icons: Warning triangle, exclamation mark, X icon. Keep them consistent across your app.
Placement: Errors should appear near the source of the problem. In forms, below the field. For page errors, prominent but not overwhelming.
Timing: Errors should appear immediately when detected. Don't hide them behind scrolling or collapsed sections.
Animation: A subtle shake or bounce can draw attention to an error without being obnoxious. Don't overdo it.
Logging and Recovery
Behind the scenes, errors need to be captured and analyzed.
Log errors properly. Capture stack traces, request details, user context. Use services like Sentry, LogRocket, or Datadog.
Monitor error rates. If a new deployment causes a spike in 500 errors, you want to know immediately.
Provide error IDs. "If this keeps happening, contact support with reference code ABC123." This helps your team debug specific issues.
Learn from errors. Recurring errors are a signal. Either the UI is confusing (causing user errors) or the system is fragile (causing technical errors). Fix the source.
Testing Error States
Most teams test the happy path thoroughly and ignore error states. Don't be that team.
Test scenarios:
- Every form validation rule
- Server returning various error codes (400, 401, 403, 404, 500)
- Request timeout
- Offline mode
- Slow connection
- Session expiration
- Permission denied
Tools help: browser dev tools can simulate offline, slow network, and blocked requests. Build a test harness that triggers error states on demand.
Error State Checklist
Before shipping, verify:
- Every error has a human-readable message?
- Messages explain what happened and what to do?
- Form errors show inline, near the problem field?
- Page-level errors have clear next steps?
- Offline state is handled gracefully?
- User work is preserved through errors?
- Errors are logged for your team to analyze?
- You've actually tested all error scenarios?
Errors will happen. Your users will forgive them if you handle them well. Clear communication, helpful guidance, and preserved work turn a frustrating moment into a manageable one.
That's the bar. Meet it, and errors become just another part of the experience. Not the end of it.