Accessible form error messages and validation
An accessible error message names the field, says in text what is wrong and how to fix it, sits next to the field and is linked to it in code, so a screen reader announces it with the field. WCAG requires the error in text (3.3.1, Level A), a suggested fix where one is known (3.3.3, Level AA) and, for errors a script adds without moving focus, a role or property that lets assistive technology announce them (4.1.3, Level AA). A red border on its own does not count.
Published . Last reviewed .
WCAG calls anything a user enters that a form does not accept an input error: a required answer left blank, or a value in the wrong format or outside the allowed values (W3C's Understanding page for 3.3.1). The error is rarely the problem. The problem is that the person never learns it happened or cannot tell how to fix it. Someone who cannot see a red outline may not notice that anything changed, and "Invalid input" leaves everyone guessing. W3C says flagging errors helps people with reduced sight and cognitive disabilities resolve them.
This guide covers what the criteria ask, how to write, place, connect and announce each message, and how to test it. The examples are invented. It is part of how to make a website accessible; labels and instructions are in accessible forms.
What WCAG requires of error messages
These six success criteria bear most directly on form errors.
| Criterion | Level | What it asks of a form | W3C's explanation |
|---|---|---|---|
| 3.3.1 Error Identification | A | An input error that is detected automatically is identified and described in text. | Understanding 3.3.1 |
| 3.3.3 Error Suggestion | AA | Where a correction is known, it is suggested, unless that would jeopardize security or the purpose of the content. | Understanding 3.3.3 |
| 4.1.3 Status Messages | AA | An error message that appears without taking focus can be presented by assistive technology, through a role or property. | Understanding 4.1.3 |
| 1.4.1 Use of Color | A | Color is not the only visual means of conveying information, so a red outline needs text with it. | Understanding 1.4.1 |
| 3.3.2 Labels or Instructions | A | Labels or instructions are provided where input is needed, and may state the data format expected. | Understanding 3.3.2 |
| 3.3.4 Error Prevention (Legal, Financial, Data) | AA | On pages that make legal commitments or financial transactions, change or delete user-controllable data, or submit test responses, submissions are reversible, checked or confirmed. | Understanding 3.3.4 |
Three points from W3C's notes shape the rest of this guide:
- No display method is mandated. Errors can be listed before the form, shown beside each field or presented in an alert or dialog, so long as they are in text. Color or an image may be added to the text but cannot replace it.
- One message can meet two criteria. In W3C's example, a message saying only that the email is not valid meets 3.3.1, while one that also gives the expected email format meets 3.3.1 and 3.3.3.
- The code connection is covered elsewhere. W3C says 3.3.1 does not itself require programmatic information about an error. Criteria such as 4.1.2 Name, Role, Value may. In GotAlt's reading, a message beside a field is also a relationship shown by position, the territory of 1.3.1 Info and Relationships.
Write each message to name the field, the problem and the fix
W3C's forms tutorial on user notification asks for messages that are concise, easy to understand and give simple instructions for resolving the problem. Four habits follow from W3C's guidance:
- Name the field the way its label does. "Expiry date", not "field 3". The same words in the label, the message and the error summary let a person match them.
- Say what is wrong in words, not in a code and not as "Invalid".
- Say how to fix it. W3C's technique G85 asks the message to give an example of correct entry, describe it or show similar valid values. Where the correction is known, offer it, as G177 does. W3C's Understanding page for 3.3.3 gives an example: for a month-name field that received "12", list the valid names or ask "Do you mean 'December'?"
- Keep what the person typed. G85's test checks that previously entered data is shown again, except in a security-related field such as a password.
| Field | Weak | Better |
|---|---|---|
| Email address | "Invalid input" | "Email address: enter an address in the format name@example.com." |
| Expiry date | A red border and no text | "Expiry date: use the format MM/YYYY, for example 03/2027." |
| First name | "Required", in red | "First name is empty. Enter your first name." |
| Month | "Error", after the user typed 12 | "Month: enter a month name from January to December. Did you mean December?" |
Show errors where people will find them
The W3C tutorial separates overall feedback, given once after a submission, from in-line feedback at each field. Use both.
- Put the result in the page title and the h1, in the pattern "3 errors: Billing address". The tutorial notes that screen reader users receive a title as soon as the page loads, and technique G83 adds that a user may otherwise assume the form was accepted and move on.
- List the errors in a summary before the form, under a distinctive heading. Each item should refer to the field's label, describe the error, say how to correct it and link to the field. W3C's technique G139 treats such a mechanism for jumping to errors as advisory, not required.
- Repeat each message beside its field, in the same words.
- Move focus on purpose. The tutorial sets focus on the first field with an error. G139's third example sets it on a link that starts the list of errors. Either gives a keyboard user a starting point. Leaving focus on the Submit button does not, in our reading.
Connect each message to its field in code
A message that only sits near a field in the layout is not tied to it for someone moving through the form with a screen reader. The W3C tutorial and technique ARIA21 tie them together with aria-describedby on the field. ARIA21 adds aria-invalid="true" to mark the field as failing validation:
<label for="expiry">Expiry date</label>
<input id="expiry" name="expiry" type="text"
aria-invalid="true"
aria-describedby="expiry-hint expiry-error">
<p id="expiry-hint">Use the format MM/YYYY.</p>
<p id="expiry-error"><strong>Error:</strong> the expiry date is not in the
format MM/YYYY. Enter it like 03/2027.</p>
- Keep the label as the field's name and the error as its description. G83 warns that some screen readers may not announce a change to a label.
- Set
aria-invalidonly after validation fails. ARIA21 says not to set it before validation has run, and MDN says not to set it on empty required fields until the person has tried to submit. - Start the message with "Error:" so it does not depend on color, as W3C's own examples do.
- Know the alternative. MDN also documents aria-errormessage, but the W3C material above uses
aria-describedby, so we show that. See ARIA basics for when to use ARIA at all.
Announce errors that appear without a page load
When a script adds an error without reloading the page, nothing moves focus, so assistive technology needs a cue. Criterion 4.1.3 covers this. An error shown in a dialog that takes focus is a change of context, which W3C says is outside 4.1.3 (see accessible modals). For the rest, W3C's technique ARIA19 uses role="alert" or a live region, and makes three points:
- The container must already be in the page when it loads, then be filled with the message. W3C says otherwise most screen readers will not speak it.
- Adding
aria-atomic="true"is needed for VoiceOver on iOS to read the errors again after more than one invalid submission. role="alert"equalsaria-live="assertive", which interrupts. W3C's 4.1.3 page lists assertive announcements for content that is not important and time-sensitive as a failure, and warns that too many live messages can make an application too chatty for screen reader users.
| When the message appears | What to do |
|---|---|
| The server returns a new page after submit | Put the error count in the title and h1, list the errors before the form and set focus on the summary or the first invalid field. |
| A script adds errors without a reload | Fill a role="alert" container that was in the page from the start, or move focus to the summary. In our reading, using both risks reading the errors twice, so choose one, then listen to confirm they are heard once. |
| A field is checked when focus leaves it | Use a live region tied to the field. W3C's example uses aria-live="assertive" so the message is read before the next field. |
| A field is checked while the person types | Use aria-live="polite", which W3C says is read once when typing stops, not on every keystroke. |
| The form is submitted successfully | Show a message such as "Your order was placed" with role="status", per technique ARIA22 on the 4.1.3 page. |
Choose when to validate, and what to do about browser messages
W3C's tutorial shows three moments to check: after submit, when focus leaves a field and while the person types. In our reading, submit is the baseline, because a server can do it without client-side scripting. Checking when the person leaves a field suits formatted data such as dates, because checking while they type would show an error most of the time, W3C says. Checking while typing needs scripting and suits fewer forms, such as username availability. MDN advises against setting aria-invalid on an empty required field before the person has tried to submit, and in our reading the same goes for a visible message.
HTML's built-in validation (required, type="email") blocks submission and shows a browser message. W3C says that meets 3.3.1 in common browser and screen reader combinations, since focus returns to the first invalid field and the message is announced. It lists drawbacks: the message may not be permanent or scroll with the page, may not enlarge when the user zooms in, is often too generic for 3.3.3, and shows only the first error. MDN's validation guide describes the novalidate attribute, which turns off the browser's own messages so you can show yours in the page. One approach, in our reading, is to keep the HTML rules, add novalidate and write the messages and summary described above.
Do not rely on color, icons or placeholders
- Color. W3C's Understanding 1.4.1 lists an error shown in red among its examples of information conveyed by color, and says an outline that is green for valid and red for invalid needs an additional indicator. The words "Error:" plus the message are that indicator. Our guide to color and links covers the same criterion.
- Contrast. Normal-size error text needs 4.5:1 against its background (1.4.3), so check the pairing on a tinted error box. Our reading is that an icon or border carrying the error should also reach 3:1 (1.4.11), though that criterion names no error state. See the color contrast guide.
- Icons. An icon beside the word "Error:" repeats it, so give it an empty alt or hide it (decorative images).
- Placeholders. A placeholder disappears when someone types and is not a label (our placeholder guide). Keep format hints in visible text beside the label.
Check it yourself
An error state exists only after someone submits a bad entry, so test each form template in that state.
- Submit the empty form, then put one wrong value in each kind of field and submit again. Does every error appear as text, name its field and say how to fix it? Is what you typed still there?
- Use only the keyboard. After submitting, where is focus? Can you follow each summary link to its field? Our keyboard accessibility test has the rest of the routine.
- Take color away. Screenshot the form with its errors showing and load it in our color blindness simulator, which has a lightness-only view. Can you still find every error, and does each one say in text what is wrong? Then check the error text and its background in the contrast checker.
- Zoom to 200%. W3C notes that default browser messages may not enlarge.
- Listen with a screen reader. Tab to an invalid field: do you hear its label, that it is invalid and the message? After a scripted submit, is the summary announced once? See how screen readers read a page.
The free accessibility bookmarklet reads the page as it is when you click it, so submit the form first and run it with the errors showing. It flags form fields with no label and fields labeled only by their placeholder, which matters because the February 2026 WebAIM Million found missing form input labels on 51% of home pages. None of its checks covers error text, aria-invalid or aria-describedby, so it cannot tell you whether a message is helpful or connected to its field. Scan my site for free reads the HTML your server sends and does not fill in or submit forms, so error messages that appear only after a bad entry are outside what it reads. What we check lists every rule.
Passing these checks does not show that a form meets WCAG or any law. For the wider routine, see how to test website accessibility.
Form error message questions
How do you write an accessible error message?
Name the field the way its label does, say in plain words what is wrong, and say how to fix it, with the expected format or an example. Keep it short and put it in text, not only in color. W3C's forms tutorial asks for messages that are easy to understand and give simple instructions for resolving the problem.
Where should form error messages go?
In two places. W3C's forms tutorial suggests a list of errors at the top of the page, before the form, under a distinctive heading, with a link from each item to its field. It also suggests a message at or near each field. Using the same wording in both helps a person match them.
How do I connect an error message to its input?
Give the message an id and point to it from the field with aria-describedby, as W3C's forms tutorial and technique ARIA21 do. Add aria-invalid="true" once validation has failed, not before. Keep the label as the field's name, because some screen readers may not announce a change made to a label.
Should form errors use role="alert"?
For errors added to the page without a reload, W3C's technique ARIA19 uses role="alert" or a live region. The container must be in the page when it loads, with the message added afterward. Because role="alert" interrupts, use it only for important, time-sensitive messages. A polite live region suits feedback while typing.
Is the browser's built-in form validation accessible?
It can meet 3.3.1, W3C says, since focus returns to the first invalid field and screen readers announce the message. The drawbacks are that messages may not be permanent, may not enlarge when zoomed, are often too generic for 3.3.3, and show one error at a time. Many sites add the novalidate attribute and write their own messages.
Is a red border enough to show a form error?
No. Success criterion 3.3.1 requires the error to be described in text, and 1.4.1 says color cannot be the only visual means of conveying information. A red border can stay as an extra cue, but pair it with a text message such as "Error:" followed by what is wrong and how to fix it.
When should validation messages appear?
W3C's forms tutorial shows checking after submit, when focus leaves a field and while typing. In our reading, submit is the baseline. Checking on leaving a field suits formats such as dates, because checking during typing would show errors most of the time. Checking while typing suits things like username availability. MDN says not to mark an empty required field invalid before the person has tried to submit.
Which WCAG criteria cover form errors?
3.3.1 Error Identification (A) and 3.3.3 Error Suggestion (AA) cover the message. 4.1.3 Status Messages (AA) covers announcing it, 1.4.1 Use of Color (A) covers color-only cues, and 3.3.4 Error Prevention (AA) covers submissions that are hard to undo, such as financial transactions and data deletion. Labels and format hints fall under 3.3.2 Labels or Instructions (A).
Run the automated part first
The free scan flags form fields with no label, among its rule-based checks. It does not submit forms, so test the error states with the steps above. No signup.
Scan my site for freeRelated guides
- How to make a website accessible: the 10-step plan these guides build on.
- Buttons vs links: which to use and why it matters.
- Accessible modal dialogs: focus that moves in, stays and comes back.
- Accessible navigation menus: menus and mega menus that work by keyboard.
- Accessible carousels: controls, pausing and hidden slides.
- Accordions, tabs and disclosures: the patterns and the native details element.
- ARIA basics: the first rule of ARIA and when not to use it.
- aria-hidden and focusable elements: a control the keyboard reaches but a screen reader cannot.
- Touch target size: the 24 by 24 pixel rule in WCAG 2.2.
- CAPTCHA accessibility: why most CAPTCHAs exclude people, and the alternatives.
- Accessible forms: labels, instructions and errors.