Error messages are copy
On the worst-written sentences on any website being the ones people read most carefully, why nobody owns them, and the three jobs a message has to do.
I watched a user test in July where someone tried to buy something three times and left without doing it.
Their phone number had spaces in it, the way people write phone numbers. The field rejected spaces. The message said “Invalid input,” in red, under the box, and it did not say which input, and there were four fields on that screen.
So they changed their email address, because that’s the field that looks technical. Then they changed it back and changed the zip code. Then they closed the tab.
The regex was two characters away from correct. But the thing that actually cost that sale was a two-word string, written by a developer, at the exact moment in the task when they cared least about the writing, and shipped without another human ever reading it.
The worst writing, read the hardest
Here’s the thing that gets me about this.
Every other piece of copy on a site is skimmed. People do not read your homepage. They do not read your about page. Your carefully argued paragraph about the company’s founding gets an average of about a second and a half.
An error message is read closely, twice, by somebody who has stopped and is concentrating, because they have been prevented from doing what they came to do and they are looking for the way out. It is, by a distance, the most attentively read text you will publish.
Nobody reads your homepage. Everybody reads the error message, twice, closely, at the exact moment they are most annoyed with you.
And it’s written by whoever was implementing the validation, in the same keystrokes as the validation, in about four seconds.
Nobody owns it
I think that’s structural rather than anybody’s fault.
The designer produces screens. Every design file I have ever been handed contains the happy path: the empty state if I’m lucky, the filled-in state, the success state. Error states appear in maybe one design in ten, and when they do it’s a generic red box with lorem ipsum in it.
The copywriter, if there is one, writes the pages. They are briefed on the proposition and the tone of voice and the calls to action. Nobody has ever handed a copywriter a list of the 41 error strings in the checkout.
So it falls to the developer, who is the only person who knows all the failure cases, and who is writing them while thinking about the failure cases rather than about the person. And then it’s never reviewed, because nobody knows it’s there. The strings aren’t in the design file, they aren’t in the content spreadsheet, and you can’t see them by looking at the site unless you deliberately break it.
The fix I’ve landed on is dull and it works: put the error states on the style guide page. All of them, rendered, with real strings. Then the designer sees them, and the account manager sees them, and somebody says “we can’t say that to a customer,” and they’re right.
The three jobs
A message has to do three things and most do one.
Say what happened, specifically, in words about the person’s world rather than about my system. Not “Invalid input.” Not “The request could not be processed.”
Say why, when the why is actionable. Sometimes it isn’t and then don’t bother.
Say what to do next. This is the one that’s nearly always missing and it’s the whole point. A message that describes a wall is not as useful as a message that describes a door.
Invalid input
→ That doesn't look like a US phone number. It should be 10 digits, and
dashes are fine.
An error occurred.
→ We couldn't save your changes because the connection dropped. Nothing
has been lost, try again.
Password does not meet requirements.
→ Passwords need to be at least 8 characters. Yours is 6.
(and show the rules before they type, not after)
Session expired.
→ You've been signed out for security after 30 minutes. Sign in again
and we'll bring you back to this page.
The pattern in the right-hand column is: a fact, in plain words, and then an instruction. And no blame anywhere, which mostly means avoiding the word “you” followed by a verb about doing something wrong. “You entered an invalid email” and “That email address is missing an @” contain the same information and only one of them is a small telling-off.
Where it goes, and whether it’s announced
Two mechanical things that turn a good message into a message that works.
It has to be next to the field it’s about. A summary at the top of a 20-field form, saying three things are wrong, is a scavenger hunt. If you want a summary, and on long forms you should, make each item a link that moves focus to the field.
And it has to be announced, or it doesn’t exist for a fair number of people. If the message appears in the DOM after a keypress and nothing tells assistive technology, a screen reader user tabs past a field that is silently rejected. Tie the message to the input, and put it somewhere that gets read out when it changes:
<label for="phone">Phone number</label>
<input id="phone" name="phone" type="tel"
aria-describedby="phone-hint phone-error" aria-invalid="true">
<p class="field__hint" id="phone-hint">10 digits. Dashes are fine.</p>
<p class="field__error" id="phone-error" role="alert">That's 9 digits, it needs 10.</p>
Never take their data away
The most expensive error message I know isn’t badly written at all. “Your session has expired” is clear, accurate and polite, and it is routinely delivered alongside an empty form that somebody spent 11 minutes filling in.
At that point the wording is irrelevant. Nothing you write in that box will make it acceptable, and the person is gone.
So: keep the values. On a validation failure, repopulate everything, including the fields that were fine. On a session timeout, hold the submission and restore it after they sign in. If a payment fails, don’t clear the address. This is occasionally a bit of work and it is more valuable than every sentence I’ve rewritten in this post.
Make them visible
The 404 and the 500 page are the ultimate orphans of all this. Nobody designs them, nobody writes them, and they’re the pages you meet at your worst moment. It’s worth 20 minutes: what happened, in one line, and then the three or four places somebody might have been trying to get to, and a way to report it.
I’ve started keeping the strings in one file rather than scattered through the validation code, mostly so somebody can read them all in one go and be appalled. That’s been the single most effective thing. Not a process, not a style guide. Just making them visible enough that a person other than me could object.