Error Handling & Validation
Inline field errors, form-level error summaries, and accessible validation timing
Overview
Accessible error handling ensures that all users — including screen reader users and those with low vision — can identify, understand, and correct form errors. Errors communicated only through color are invisible to many users. Error messages that are not programmatically associated with their fields are never announced on focus. A well-structured error summary gives users a roadmap to fix all problems at once.
WCAG Criteria:
- 3.3.1 Error Identification — errors must be identified and described in text
- 3.3.3 Error Suggestion — suggestions for correction must be provided when known and safe
- 3.3.4 Error Prevention — covered transactions must be reversible, checked, or confirmed
- 1.4.1 Use of Color — color must not be the only visual means of conveying information
Key requirements:
- Never use color alone to indicate an error (WCAG 1.4.1) — always include a text message
- Use
aria-invalid="true"on the field andaria-describedbypointing to the error message - Choose one announcement strategy: focus a headed summary or update a concise live message; avoid duplicate channels
aria-errormessagehas incomplete browser support — usearia-describedbyas the primary association- Validate inline on blur for individual fields; validate on submit for first-pass validation
- Error summaries should list all errors with links to the corresponding fields
Inline Field Error
Color-Only Error vs. Described Error with aria-invalid
View inaccessible code
<!-- Only a red border — no text message, no aria attributes -->
<label for="error-handling-bad-email">Email</label>
<input
id="error-handling-bad-email"
type="text"
value="not-an-email"
style="border-color: red"
/>View accessible code
<label for="error-handling-good-email">Email</label>
<input
id="error-handling-good-email"
type="text"
value="not-an-email"
aria-invalid="true"
aria-describedby="error-handling-good-email-error"
/>
<span id="error-handling-good-email-error">
Please enter a valid email address.
</span>What’s wrong with color-only errors?
- The red border is invisible to screen reader users — no error is ever announced
- Users with color vision deficiencies may not distinguish the red border from a normal one
- There is no
aria-invalidattribute, so assistive technology does not know the field is in an error state - No text message exists to describe what went wrong or how to fix it
Expected semantics on focus:
| Version | Programmatic result |
|---|---|
| Inaccessible (color only) | The field has a name and value, but no invalid state or error description. |
| Accessible (described error) | The field exposes its name, invalid state, value, and associated correction text. |
Form Error Summary
Inline-Only Errors vs. Error Summary with Links
View inaccessible code
<!-- No error summary — errors appear inline with no announcement -->
<form onsubmit="showErrors()">
<label for="name">Name</label>
<input id="name" type="text" />
<p class="error" style="color:red; display:none">
Name is required.
</p>
<label for="email">Email</label>
<input id="email" type="text" />
<p class="error" style="color:red; display:none">
Please enter a valid email.
</p>
<button type="submit">Submit</button>
</form>View accessible code
<form onsubmit="validateForm(event)">
<!-- Focus one headed summary; inline errors remain descriptions. -->
<div id="error-summary" tabindex="-1" hidden></div>
<label for="error-handling-good-name">Name</label>
<input
id="error-handling-good-name"
type="text"
aria-describedby="name-err"
/>
<span id="name-err"></span>
<label for="error-handling-good-sum-email">Email</label>
<input
id="error-handling-good-sum-email"
type="text"
aria-describedby="email-err"
/>
<span id="email-err"></span>
<button type="submit">Submit</button>
</form>
<script>
function validateForm(e) {
e.preventDefault();
// 1. Populate the summary with linked errors
summary.innerHTML = `
<h3>2 errors found</h3>
<ul>
<li><a href="#name">Name: required</a></li>
<li><a href="#email">Email: invalid</a></li>
</ul>`;
summary.hidden = false;
summary.focus(); // move focus to summary
// 2. Mark fields invalid
nameInput.setAttribute('aria-invalid', 'true');
// 3. Inject inline error text
nameErr.textContent = 'This field is required.';
}
</script>What’s wrong without an error summary?
- After submission, sighted users may see red text but screen reader users get no notification that errors occurred
- Without
role="alert"on a pre-existing container, the error messages are not announced - There is no way for a screen reader user to get an overview of all errors at once
- Inline errors without
aria-invalidoraria-describedbyare not associated with their fields
Expected behavior after submit:
| Version | Focus and semantic result |
|---|---|
| Inaccessible (inline only) | Focus stays on Submit and the new error text is not associated with its fields. |
| Accessible (summary + inline) | Focus moves to the headed summary; its links identify each field, and every invalid field exposes its own description. |
Error Prevention for Important Actions
WCAG 3.3.4 applies to submissions that create legal commitments or financial transactions, modify or delete user-controlled data, or submit test responses. At least one safeguard must exist: make the action reversible, check the data and allow correction, or provide a review-and-confirm step.
Immediate Irreversible Deletion vs. Review and Recovery
Delete the account and all saved projects.
View inaccessible code
<button onclick="deleteAccountImmediately()">Delete account</button>Review account deletion
This removes 12 projects and ends the subscription. You can restore the account for 30 days.
View accessible code
<section aria-labelledby="review-title">
<h3 id="review-title">Review account deletion</h3>
<p>This removes 12 projects. You can restore the account for 30 days.</p>
<button>Confirm deletion</button>
<button>Go back and correct</button>
</section>Re-validation must clear stale aria-invalid and descriptions when a field becomes valid. Security-sensitive forms may limit how much detail they expose, but should still identify an error and provide a safe correction path.