Nobody minds that an error happened. What people mind is being handed a message that doesn't tell them what to do about it. Error copy is often cryptic, or subtly blaming, or just irrelevant to the actual problem — and the honest goal for any error message should be to leave the reader thinking "I can fix this," not "I must have done something wrong."
The error message is arguably the moment your product is under the most pressure to perform, precisely because the user is already frustrated before they even read it. It's your one chance in that moment to either help or make things measurably worse. A confusing, jargon-heavy message tends to send people into randomly trying things until they give up. A message that implicitly blames the user gets internalized as "I must be bad at this," which quietly erodes trust in the product. A message that's just vague sends people looking for outside help — a forum post, a support ticket, a friend who's used the product before. Only a genuinely clear, specific message actually gets someone unstuck.
The shape that tends to work: state what went wrong, give context on why if it's useful, tell the reader exactly how to fix it, and leave a safety valve — a way to get help if the fix doesn't work. "Error 405. Method not allowed" fails on every count: the jargon means nothing to a non-technical user, there's no guidance, and there's no next step, so the reader is left thinking "what does 405 mean?" and giving up. Compare that to "Your file is too large to upload (maximum 10 MB). Please compress your image or choose a smaller file, then try again" — it explains the problem, states the actual limit, and suggests exactly what to do next.
Be Specific, Not Generic
| Generic | Specific |
|---|---|
| Error: Invalid input | Your email address is missing the @ symbol |
| Server error occurred | We're temporarily experiencing heavy traffic. Please try again in 2 minutes. |
| Format not supported | We accept JPG, PNG, and GIF files. You selected TIFF. |
| Connection failed | Your internet connection dropped. Check WiFi and try again. |
A generic message costs the reader a second trip — to a search engine, to support, to guessing — that a specific one would have avoided entirely.
Use Plain Language, Not System Language
| Technical | Plain Language |
|---|---|
| HTTP 401 Unauthorized | You need to log in to access this |
| Payload validation failed | The information you sent wasn't complete |
| Authentication token expired | Your login time ran out, please log in again |
| Query syntax error | Your search didn't work. Try fewer words. |
A status code or an internal system term means nothing to someone who's never seen your backend. Say what happened in words a non-technical friend would understand.
Don't Blame the User
| Blaming | Helpful |
|---|---|
| Invalid format entered | Date should be MM/DD/YYYY |
| Wrong credentials provided | Email or password incorrect |
| Too many failed attempts | You've tried 4 times. Try again in 15 minutes. |
| Improper file type | We accept PDF files. You selected DOC. |
Blaming language makes users feel stupid, and that feeling sticks to your product, not just to the moment of the error. Describing the situation neutrally instead of accusing the user of doing it wrong is a small wording shift with an outsized effect on trust.
Always Offer a Next Step
| Problem-Only | Problem Plus Solution |
|---|---|
| Username already exists | This username is taken. Try adding a number (e.g., John2026) or choose something different. |
| Payment declined | Your card was declined. Check: card number, expiration date, CVV. Or try a different card. |
| Download failed | Download failed. Check your internet connection and try again. If it continues, try a different browser. |
Even when there's no clean fix, offer something — "contact support" is a weak next step, but it's still a next step, and it's better than leaving someone at a dead end.
A few smaller mistakes are worth watching for too: a message that flashes and disappears before anyone can read it, all-caps text that reads as the app yelling at you, relying on red text alone to signal urgency (which fails for colorblind readers — pair color with an icon or a word like "warning"), and generic codes standing in for a real description. None of these are hard to fix once you're looking for them; they mostly creep in because nobody's specifically responsible for auditing error copy after launch.
Applying all of this to a few common cases: a password-requirements error is stronger when it states the actual rule and what's still missing ("at least one special character and 8 characters — you're at 7 with no special character yet") rather than a bare "special characters required." A declined payment is far less frustrating when it lists the likely causes (insufficient funds, expired card, a fraud flag) and gives the reader something to check, rather than just "card declined." And a network error that mentions checking the connection and notes current system status gives someone somewhere to look instead of just a dead "connection timeout."
Good error messages, in my experience, share five habits: they put responsibility on the system rather than the user, they explain the situation without jargon, they offer an actual next step, they read as if the author understood the reader would be at least a little frustrated, and — as a cumulative effect of all of that — they build trust rather than eroding it. If you want to know whether it's working, the metrics that matter are simple: are error-related support tickets trending down, is the average time to resolve an error dropping, and are the same errors showing up again and again for the same users (a sign the message isn't actually helping them fix the root cause).
An error message isn't a failure state to apologize your way through — it's one of the few moments a product gets to prove it's actually looking out for the person using it. Write it the way you'd explain the problem to a friend: clearly, specifically, and without making them feel bad for hitting it.