Error messages and empty states are usually designed last. By the time a product team gets to them, the deadline is close, the energy is low, and the temptation is to write "Something went wrong. Please try again." and move on. The result is a product that communicates competently during the happy path and falls apart the moment a user does something unexpected.
This matters more than most teams assume. The moments when a user encounters an error or an empty state are often the moments when they decide whether to keep using a product or abandon it. A well-designed error message can recover a user's trust. A poorly designed one sends them to a competitor.
Why Error Messages Fail
The most common failure mode is vagueness. "An error occurred" tells the user nothing: not what went wrong, not whether it was their fault, not what they should do next. Vague errors force users to guess, and most of them will guess wrong or give up.
The second failure mode is blame. Error messages that frame user mistakes as user failures ("Invalid input. Please check your form.") are technically accurate and emotionally counterproductive. Users who feel blamed become frustrated rather than motivated to correct the problem.
The third failure mode is context blindness. An error message that makes sense to an engineer often makes no sense to an end user. "HTTP 422: Unprocessable Entity" means something specific in a technical context. It means nothing to someone who just tried to upload a profile photo.
Four Principles for Writing Effective Error Messages
1. Be specific about what went wrong
A specific error message tells the user exactly what the system could not handle and why. Compare:
- Vague: "Your password is invalid."
- Specific: "Your password needs at least one number and one uppercase letter."
The specific version gives the user everything they need to fix the problem immediately. The vague version leaves them guessing which rule they violated and potentially trying multiple times.
2. Tell users what to do next
An error message without a recovery path is a dead end. Every error should answer the question "and now what?" For recoverable errors, this means a clear next action. For unrecoverable errors, it means an alternative path.
Recoverable: "Your session has timed out. Sign in again to continue." (with a direct link to the sign-in page)
Unrecoverable: "This file format is not supported. Accepted formats are PDF, PNG, and JPG."
3. Write like a person, not a system
Error messages written in passive voice or system language ("The operation was aborted due to an unresolvable conflict") create distance between the product and the user. Messages written in direct, plain language maintain the tone of a helpful product.
Compare:
- System voice: "The requested resource could not be located."
- Human voice: "We could not find that page. Try searching for what you need."
The second version does the same job without sounding like a stack trace.
4. Avoid blame, even when the error is the user's fault
"Invalid input" and "incorrect password" both frame the user as having done something wrong. "Try a different email address" and "Check your password and try again" convey the same information without making the user feel at fault. This is not about sugarcoating; it is about keeping the user emotionally engaged with solving the problem rather than defending themselves.
Error Message Patterns by Context
Different types of errors call for different patterns.
Inline validation: Show errors in real time as the user fills out a form, adjacent to the specific field that has a problem. Do not wait until the user submits the form to surface all errors at once. The Nielsen Norman Group's research on form design consistently shows that inline validation reduces form abandonment and correction cycles.
Form submission errors: When a user submits a form with multiple problems, list every issue at the top of the form and repeat the specific error adjacent to each field. Forcing users to hunt for their mistakes adds unnecessary friction.

Photo by Obi Onyeador on Pexels
System-level errors: 500-level errors (server errors) are not the user's fault and should not imply that they are. "Something went wrong on our end. We're looking into it. Try again in a moment." is honest and does not leave the user wondering what they did.
404 errors: A 404 page is an opportunity to redirect rather than dead-end. A good 404 page acknowledges the broken URL, suggests what the user might have been looking for, and provides navigation back to useful content. A search bar is often more helpful than a list of suggested pages.
Destructive action confirmation: Errors and warnings before irreversible actions (deleting data, sending a message to a large list) should clearly communicate the consequence, not just ask for confirmation. "Delete this account? This cannot be undone and all your data will be permanently removed." is better than "Are you sure?"
Accessibility in Error Messages
Error messages need to be accessible to users with disabilities, which means more than visible text. Screen readers need to be notified when errors occur. The Web Accessibility Initiative guidelines specify that form errors should use aria-live or aria-describedby to associate error messages with their fields programmatically, not just visually.
Color cannot be the only indicator of an error. Red text is invisible to users with certain color vision deficiencies. Icons, text labels, or pattern changes need to accompany color changes. MDN Web Docs has practical guidance on accessible form validation patterns that meet WCAG standards.
Error messages should also be persistent. An error that disappears after a few seconds may clear before a user with a motor disability has had time to read and act on it.
Designing Empty States
An empty state is what a user sees when a view has no content yet. This happens at first use (a new app with no data), after a search with no results, or after a user has cleared a list or filtered content to zero items.
Empty states are often skipped in design mockups because they only appear in edge cases. In practice, they appear for every new user, every failed search, and every time a user exhausts a feed or list. They are not edge cases; they are standard states.
"Empty states are a test of whether a product was designed for first-time users or just for returning ones. If a new user lands on a blank screen with no guidance, the product has already failed its onboarding before it started. Every empty state should either teach the user what to do next or invite them to take the first step." - Dennis Traina, founder of 137Foundry
A well-designed empty state does three things: acknowledges the state, explains why it is empty, and gives the user a path forward.

Photo by Christina Morillo on Pexels
Five Empty State Patterns
1. First-use orientation
When a user has just signed up and landed on an empty view, the empty state is an onboarding opportunity. Show them what the view will look like with data, explain how to add their first item, and make the call to action prominent. A dashboard with no data points and no explanation is disorienting; a dashboard with a visible "Add your first project" prompt is welcoming.
2. No-results search
When a search returns nothing, do not just say "No results found." Suggest alternative search terms, check for typos, broaden the criteria, or show related content. The goal is to keep the user searching rather than abandoning the search. Showing what categories of content exist helps users understand what the search is capable of finding.
3. Filtered to zero
When a user applies filters that result in no matching items, show which filters are active and make it easy to clear them. A "Clear filters" button adjacent to the empty state reduces the work required to see any results again.
4. Completed state
When a user has finished everything (all tasks done, inbox zero, no notifications), the empty state is an achievement, not a problem. A message that acknowledges the completed state ("All caught up!" or "No pending items") feels better than a generic empty screen. This is a small moment, but it is an opportunity to reinforce positive behavior.
5. Error-caused empty state
When content fails to load due to a connection problem or server error, the empty state and the error message should work together. Show a clear explanation of why the content is unavailable and provide a retry action. Do not leave the user with a blank screen and no explanation.
Applying This to Your Product
The process for improving error messages and empty states across an existing product:
- Audit all error states by going through every flow and intentionally triggering errors: submit invalid forms, break expected inputs, disconnect from the network during operations.
- Inventory every empty state by identifying all views that can appear with no data.
- Apply the four principles to each error message: specific, actionable, human, blame-free.
- Add a path forward to every empty state.
- Test with real users, specifically first-time users for empty states.
137Foundry's web development team works with companies on UX audits that include error and empty state reviews as part of a broader services engagement. If you want a structured framework for evaluating these states across a complex application, this is a good entry point.
For a research-backed perspective on what users experience during errors, the Nielsen Norman Group publishes free articles on form UX and error recovery patterns that are grounded in user testing rather than theory.

Photo by Abdulvahap Demir on Pexels
Getting This Right
Error messages and empty states share a common design requirement: they need to be useful, not just present. A message that exists but fails to help is not better than no message; in some cases it is worse, because it creates a false sense that the product has communicated something meaningful.
Designing these states well requires treating them as first-class parts of the product rather than edge-case cleanup. That means writing error copy with the same care as marketing copy, designing empty states before they are needed rather than after, and testing them with the same rigor applied to the primary flows.
Users do not evaluate a product only on its happy path. They evaluate it on how it behaves when something goes wrong. User experience is cumulative, and errors handled well contribute to that cumulative impression as much as features delivered smoothly. The goal is not a product that never has errors; it is a product where errors, when they happen, feel handled rather than ignored.