3.3.1 Error Identification
Level: A | Principle: Understandable | Since: WCAG 2.0 | Automation: Partial (axe-core)
What This Means
When a form input error is automatically detected, the item in error must be identified and the error described to the user in text. A red border alone is not sufficient — the error must be communicated in words so that screen reader users and color-blind users know what went wrong and where.
Who This Affects
- Screen reader users — they cannot see visual cues like red borders; they need text-based error messages associated with the field
- Color-blind users — relying solely on color (red border, red text) to indicate errors is invisible to them
- Cognitive disability users — clear, specific error messages help them understand what needs to be corrected
- Everyone — descriptive error messages reduce form abandonment
Common Pitfalls
1. Error indicated only by color
<!-- Bad: only a red border signals the error -->
<input type="email" style="border: 2px solid red">
<!-- Good: text error message + aria association -->
<label for="email">Email</label>
<input id="email" type="email" aria-describedby="email-error" aria-invalid="true">
<p id="email-error" role="alert">Please enter a valid email address.</p>
2. Generic error message with no field identification
<!-- Bad: which field has the error? -->
<div class="error-banner">There was an error. Please fix it and try again.</div>
<!-- Good: error identifies the specific field -->
<div role="alert">
<p>Please correct the following errors:</p>
<ul>
<li><a href="#email">Email: Enter a valid email address</a></li>
<li><a href="#phone">Phone: Enter a 10-digit phone number</a></li>
</ul>
</div>
3. Error not programmatically associated with the field
<!-- Bad: error text exists but is not linked to the input -->
<label for="name">Name</label>
<input id="name" type="text">
<span class="error">Name is required</span>
<!-- Good: aria-describedby links the error to the input -->
<label for="name">Name</label>
<input id="name" type="text" aria-describedby="name-error" aria-invalid="true">
<span id="name-error" class="error">Name is required</span>
How to Fix
Associate errors with fields using aria-describedby
<label for="password">Password</label>
<input
id="password"
type="password"
aria-describedby="password-error"
aria-invalid="true"
>
<p id="password-error" role="alert">
Password must be at least 8 characters.
</p>
Provide an error summary at the top of the form
<form>
<div role="alert" aria-labelledby="error-heading">
<h2 id="error-heading">2 errors found</h2>
<ul>
<li><a href="#email">Email address is required</a></li>
<li><a href="#zip">ZIP code must be 5 digits</a></li>
</ul>
</div>
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email-err">
<p id="email-err">Email address is required</p>
<label for="zip">ZIP code</label>
<input id="zip" type="text" aria-invalid="true" aria-describedby="zip-err">
<p id="zip-err">ZIP code must be 5 digits</p>
</form>
Use aria-invalid to mark fields with errors
<!-- No error -->
<input id="name" type="text" aria-invalid="false">
<!-- Error present -->
<input id="name" type="text" aria-invalid="true" aria-describedby="name-error">
How to Test
- Submit a form with intentionally invalid data (empty required fields, wrong email format, invalid phone number).
- Verify each error is described in visible text that identifies the specific field (not just "an error occurred").
- Inspect the HTML to confirm each error message is programmatically associated with its field using
aria-describedbyand the field hasaria-invalid="true". - Check that errors are not communicated solely by color (e.g., red border without text).
- Open a screen reader, Tab to a field with an error, and confirm both the label and the error message are announced.
- Pass: Every error is identified in text, names the specific field, and is programmatically linked to the input via
aria-describedby. - Fail: Any error is communicated only by color, lacks a text description, does not identify the field, or is not linked to the input.
axe-core Rules
| Rule | What It Checks |
|------|---------------|
| aria-input-field-name | ARIA input fields must have an accessible name (related) |