( Understandable / WCAG 3.3.1 )
Form error is not clearly identified
What is this issue?
A form field fails validation (it’s empty when required, or its value doesn’t match an expected format), and the resulting error state isn’t clearly identified for every user. This can happen several ways: the error exists only as a color change (a red border, no text), the error text exists but isn’t programmatically connected to the field it describes, or a generic banner appears somewhere on the page (“There was a problem with your submission”) with no indication of which field, out of potentially many, actually caused it.
The field might be perfectly labeled under normal conditions; this rule is specifically about the error state, the moment something goes wrong and the interface needs to communicate exactly what and where.
Why does this matter?
A sighted user scanning a form after a failed submission can often spot a red-bordered field or a nearby error message at a glance, even if the underlying markup doesn’t formally connect the two. A screen reader user has no equivalent visual scan: they navigate field by field, and if the error text isn’t announced as part of that specific field’s context, they have no way to discover it except by re-tabbing through the entire form hoping to stumble across it.
This turns a routine correction into a search problem. On a longer form (an application, a multi-field checkout), an unclear error can mean submitting the same broken form repeatedly, each time getting the same vague “there was a problem” response with no way to identify what actually needs to change, until the user gives up entirely.
Who is affected?
- Screen reader users: encounter a form that appears to reject their submission with no way to locate which specific field caused it, since the error text either doesn’t exist, isn’t associated with the field, or isn’t announced when the field receives focus.
- Cognitive disabilities: users who rely on clear, immediate feedback to correct a mistake face repeated failed submissions with no growing understanding of what’s wrong, since a vague or disconnected error provides nothing to learn from between attempts.
What users experience
Sofia uses NVDA on her Windows laptop to fill out a job application form. She submits it and the page reloads with a banner at the top reading “Please correct the errors below,” but as she tabs through the form field by field, NVDA announces each field’s normal label with no mention of any error, since the actual invalid field (a badly formatted phone number) is marked only with a red outline and no connected error text. She resubmits twice more, getting the identical unhelpful banner each time, before she gives up and emails the company directly instead of completing the online form.
How do I fix it?
Add visible error text describing the specific problem, place it near the field it describes, and connect the two programmatically with aria-describedby pointing at the error text’s id, plus aria-invalid="true" on the field itself. This works because aria-describedby makes the error text part of what’s announced whenever the field receives focus, so a screen reader user gets the error automatically the moment they reach the field, not only if they happen to read a separate banner first.
Set aria-invalid="true" only while the error is active, and remove it once the field is corrected, so the field’s state accurately reflects reality rather than permanently flagging a once-invalid field as broken. If you also show a summary of all errors at the top of the form, treat it as a helpful addition, not a substitute for the field-level association: both should exist together.
Code Examples
<label for="email">Email</label>
<input id="email" type="email" class="input-error">
<p>Invalid value</p><label for="email">Email</label>
<input
id="email"
type="email"
aria-invalid="true"
aria-describedby="email-error"
>
<p id="email-error">Enter an email address in the format name@example.com.</p>The fixed version connects the error text to the field through aria-describedby, so a screen reader announces “Email, invalid entry, Enter an email address in the format name@example.com” the moment the field receives focus, not a disconnected paragraph the user has to independently discover and match back to the right input.
Framework Examples
Managing the id that links a field to its error message gets error-prone in component-driven forms, since a reusable FormField component rendered multiple times on one page needs a unique, stable id for every instance to avoid aria-describedby references colliding. React’s useId() hook generates that unique identifier per component instance automatically.
import { useId } from 'react';
function FormField({ label, error, ...inputProps }) {
const inputId = useId();
const errorId = useId();
return (
<div>
<label htmlFor={inputId}>{label}</label>
<input
id={inputId}
aria-invalid={error ? 'true' : undefined}
aria-describedby={error ? errorId : undefined}
{...inputProps}
/>
{error && <p id={errorId}>{error}</p>}
</div>
);
}
Conditionally setting aria-invalid and aria-describedby only when an error prop is actually present means the field’s accessible state changes dynamically with its real validation status: no error, no aria-invalid, and no stale aria-describedby reference left pointing at error text that isn’t currently rendered.
Common Mistakes
Mistake: “A red border around the field is a clear enough error indicator.” Color alone conveys nothing to a screen reader, and it’s an unreliable signal for anyone with low vision or color blindness even visually. An error needs a text description a screen reader announces, not just a visual style change.
Mistake: “I put an error message on the page, so the requirement is met.” Presence of error text somewhere on the page isn’t the same as that text being identified as belonging to a specific field. Without aria-describedby connecting the two, a screen reader user has to discover the disconnected text independently and guess which field it refers to.
Mistake: “A generic ‘there was a problem, please check the form’ banner is sufficient since at least something tells the user to look.” A banner with no field-level detail forces the user to re-scan the entire form to find the actual problem, which is precisely the search-and-guess burden this criterion exists to eliminate. Identify the specific field, not just the fact that a field exists.
How RedFlag Detects This
Guidance only: RedFlag documents this issue but does not currently flag it; verify manually. RedFlag’s own coverage model records zero automated detection for this criterion. Simulating a form submission, generating a validation error, and evaluating whether the resulting error state is clearly identified and programmatically associated would require RedFlag to actually trigger form validation logic, something the current static DOM scan does not do.
False negative: every case, since RedFlag never triggers form validation or evaluates error states automatically: a form with completely broken error identification passes every automated scan with no flag raised. False positive: not applicable, since no automated check runs. Manual step: the Manual Testing steps below are currently the only way to catch this issue; deliberately submit invalid data to every form on a page and evaluate what a screen reader announces in response.
Manual Testing
- Open a form in Chrome or Firefox with NVDA or JAWS running.
- Submit the form with at least one required field left empty or one field containing an invalid value.
- Tab to the invalid field and listen to what’s announced: it should include both the normal field name and a specific description of what’s wrong (“Email, invalid entry, Enter an email address in the format name@example.com”), not just the label alone.
- If the error is announced only as a separate, disconnected message elsewhere on the page, or not announced at all when the field receives focus, the check fails.
Related WCAG Success Criteria
3.3.1 Error Identification: If an input error is automatically detected, the item that’s in error must be identified and the error described to the user in text. A visual-only or disconnected error message fails this criterion at its core requirement: identification in text, associated with the specific item.
Related Issues
Error message does not explain how to fix input is the natural next step once a field’s error is correctly identified: this rule gets the user to the right field; that one makes sure the message once there actually helps them fix it.
Form field has more than one label shares the same underlying theme of a field’s announced information becoming unreliable or confusing at exactly the moment a user needs clarity most.
Form field autocomplete attribute is missing or invalid reduces how often users encounter form errors in the first place by supporting accurate autofill: fewer manual entry mistakes means fewer error states this rule has to cover well.
User must re-enter information already provided in the same process shares this rule’s broader concern with form-completion friction: both target moments where a form makes recovering from or avoiding a mistake harder than it needs to be.
Form input has no label is the baseline requirement this rule assumes is already met: clearly identifying an error on a field that has no name to begin with compounds two separate failures at once.
References
- W3C Understanding 3.3.1: Error Identification
- W3C Technique ARIA21: Using aria-invalid to indicate an error field
- W3C Technique G83: Providing text descriptions to identify required fields that were not completed
- MDN: aria-invalid
Frequently asked questions
Does a red border around the invalid field count as identifying the error?
Not on its own. A red border is a color-only visual cue that conveys nothing to a screen reader and can be invisible or hard to distinguish for some low-vision and color-blind users. It needs to be paired with a text description and a programmatic association like aria-describedby.
Is aria-invalid enough by itself to identify an error?
It communicates that a field failed validation, but not what the actual problem is. aria-invalid="true" tells a screen reader the field has an error; pairing it with aria-describedby pointing at real error text tells the user what that error actually is.
How is this different from Error message does not explain how to fix input?
This rule is about whether an error is identified and associated with the right field at all. Error message does not explain how to fix input assumes the error has already been correctly identified and instead evaluates whether its wording gives the user enough information to actually correct the mistake.
Does a summary of all errors at the top of the form satisfy this requirement?
An error summary is good practice and genuinely helps, especially for quickly scanning what went wrong, but it does not replace field-level identification: a screen reader user still needs each specific invalid field to announce its own error when they reach it, not just a list read once at the top.
Does this apply to client-side validation as well as server-side form submission errors?
Yes, both. Whether the error is caught instantly by JavaScript as someone types or only surfaces after a full server round-trip on submit, the same requirement applies the moment an error state exists: it must be clearly identified in text and associated with its field.