Form Errors That Screen Readers Actually Hear: aria-describedby and WCAG 3.3.1
Submit a form with one bad field and watch what a screen reader user gets. On most storefronts the answer is nothing. The page reloads, a border turns red somewhere above the fold, and the person who cannot see the color has no idea which field failed or why.
What 3.3.1 actually requires
Success Criterion 3.3.1, Error Identification, is Level A, which puts it in the oldest and least negotiable part of WCAG. When an input error is automatically detected, the item in error must be identified and the error described to the user in text. Color alone does not count, and a red border without a text message fails the criterion on its own. The error message has to be present in the DOM, it has to name the field and the problem, and it has to be associated with the field so assistive technology announces it when the field gets focus.
Three other criteria ride on the same submit. 3.3.3, Error Suggestion, is Level AA and asks for a correction when one is known: enter a five digit ZIP code beats invalid entry. 4.1.3, Status Messages, is Level AA and covers errors that appear without focus, like a summary at the top of the page after submit. And 1.4.1, Use of Color, is the one the red border alone breaks. One rejected field can fail four criteria at once, which is why forms show up in demand letters so often. Seyfarth Shaw counted 3,117 federal website accessibility lawsuits in 2025, and forms are one of the most tested surfaces because they are so easy to break.
The wiring that passes
The pattern that passes NVDA and JAWS consistently has four parts. First, the error text sits in the DOM next to the field, in plain text, naming the problem in specific words. Second, the input points at it with aria-describedby, listing the hint id and the error id space separated, so the message is read when the field receives focus. Third, the field carries aria-invalid="true" while it is in error, and the attribute comes off the moment the value is corrected. Fourth, on a failed submit, focus moves to the first invalid field or to an error summary, and the summary is exposed in a live region so it gets announced.
Two details trip teams that have the first three right. Native browser tooltips are inconsistently exposed to assistive technology, so the house pattern suppresses them with novalidate on the form and renders its own text errors instead. And validation timing matters: validate on blur the first time, then re-validate on each keystroke after the field has been marked invalid, so the error clears the moment the value is fixed. Validating on every keystroke from the start interrupts typing and announces errors for values the person has not finished entering.
How to test it in five minutes
You need a screen reader and a form with a submit button, nothing else. Tab to the first field, enter something wrong, and submit. The error should be announced without you hunting for it. Tab back to the field and confirm the message is read again when the field gets focus. Then fix the value and confirm the error clears and the aria-invalid attribute is gone. If the message only appears as a tooltip, or only as a red border, or sits in a summary at the top that is never announced, the form fails 3.3.1 even though a sighted tester would call it fine. For the same failure mode in a different component, see Live Regions: What Toast Messages Need to Say Out Loud, and for the checkout version of this test, Accessible Error Suggestions on Checkout Forms.
Frequently asked questions
Does a red border plus red text count as identifying the error?
No. WCAG 3.3.1 requires the error to be described in text, and color alone fails 1.4.1 as well. A screen reader does not announce color, and a colorblind user may not perceive the change. Add a text message tied to the field with aria-describedby.
Is aria-describedby better than aria-errormessage?
For production sites today, yes. aria-errormessage was designed for exactly this job, but aria-describedby has broader assistive technology support as of early 2026. Point aria-describedby at the error message element and keep the message in the DOM permanently.
Do inline errors need a live region too?
Not strictly. An inline error tied to its field with aria-describedby is announced when the field receives focus. Errors that appear without focus, such as a submit-time summary or a server-side failure, do need a live region under 4.1.3.
When should the error appear, on submit or as I type?
Validate on blur the first time, then re-validate on each keystroke after the field is marked invalid. Validating on every keystroke from the start interrupts typing and announces errors for half-finished values.