Error messages must be tied to the field through accessibility properties
Aliases: aria-describedby error · aria-invalid · accessible error
What it is
A red sentence next to a field is joinable for people who can see. When a reader enters that field, if the error sentence is not this control’s description, what is heard is the name and “edit box.” Tying through accessibility properties means the error text has a stable id, the field points at it with aria-describedby (or equivalent), and invalid state is exposed while invalid. A top list, moving focus, and not relying on color alone do not replace this binding. The label association is the name. This association is the current error description.
Why it happens
The accessible description is the second sentence spoken on entering the control. Without it, the reason exists only in visual layout. People would have to leave the field and “read nearby” to hear the error; fill mode does not wander. A second layer: description lists concatenate. If the field already hangs format help on describedby, the error must be appended to that same chain—not replace the help, and not hang on a node the reader cannot find. When the error goes, it must drop off the chain and invalid state must drop, or a stale reason becomes the current description. aria-invalid does not carry the reason, only “invalid now.” The reason lives in the description. Missing either, the reader either does not report invalid, or reports invalid without saying what to change.
Studying it
After a failed submit, enter only the field with a reader (skip the top list) and record whether the reason and invalid state are heard. Compare visual red copy only, describedby pointing at the error, and the error announced once in a live region.
Independent variables: describedby present, aria-invalid present, whether help and error share a chain, whether properties update after the error clears.
Dependent variables: whether the reason is heard on entering the field, whether a stale reason is heard, whether re-entering after a one-shot announcement still hears it.
A one-shot live announcement does not replace the description on enter—people leave and re-enter while fixing. Automation can see whether attributes exist; listening confirms which sentence is read.
Where it stops holding
Errors on custom dropdowns or a canvas cannot hang on a native input; hang the description on the role node that actually takes focus. Multiple errors (format + required) should become one description sentence so the reader does not speak two contradictions. After a language switch the error node’s id can stay while the text changes; if the error node is destroyed and rebuilt, describedby must be rewritten. Print has none of these properties.
Applying it
- Give every field-level error a stable id. While invalid, the field’s
aria-describedbyincludes that id, and invalid state is set. - If help is already described, add the error id to the same
describedbylist; do not overwrite the help. - When the value is legal, drop the error id and invalid state together so a stale reason is not spoken.
- Verify: a reader entering an invalid field hears name, invalid, and reason. After it is legal, entering again does not hear the reason. In the tree, the description points at the same node as the on-screen red sentence. Put the error in a one-shot live announcement without
describedbyas a failing control.
Related
- Within the group: H1.15.1 Every input needs a programmatic association with its visible label · H1.15.2 A placeholder used as a label loses the field’s meaning once filled · H1.15.4 Required state needs a cue both visual and non-visual
- Adjacent: H3.11 Accessible error announcement · H1.06 Error summaries · J5.11 Correct use of ARIA
- Search terms:
aria-describedby·aria-invalid·error message