Skip to content

Form Error Association (Screen Reader) ​

You fill in a form, press Send, and "This field is required" appears in red under the e-mail field. If you use a screen reader, that text may not exist for you: when you reach the field the reader says "Email, edit, blank" and nothing else. You don't know why the submit did nothing, or which field to fix.

This test looks for exactly that: error messages that are visible on screen but that the screen reader does not read when the user reaches the field.

Scope: which errors it gets to see

The tool does not type into the fields. It only sees the error messages that appear in two situations:

  1. When the submit button is pressed with every field empty. The form needs a recognisable submit button (Send, Search, Continue, Sign up…).
  2. When a field is entered and left without typing, on sites that validate the moment you leave the field.

An error that only shows up once something is typed (a malformed e-mail, a password that is too short, inconsistent dates) is out of reach. If a case does not fit those two situations, the tool was never going to report it.


What it checks, in two sentences ​

  1. That every error message shown next to a field is connected to that field, so the reader announces it when the field gets focus.
  2. That a field drawn in an error state (red border or red text) also says it has an error, so the reader announces "invalid entry".

The first is a WCAG 1.3.1 issue. The second is reported as a Best Practice, not a failure.


What the tool does ​

The same thing a person in a hurry would do:

  1. Finds the forms on the page, including widgets that are not a "real" form but behave like one: a flight or hotel search with its Search button, a newsletter block with its Send button.
  2. Presses the submit button with nothing filled in, using the keyboard. The page is kept from navigating away so the tool can keep looking.
  3. Waits for the messages to appear, including the ones that take a while because the server validates them or the form shows a loading state.
  4. Enters and leaves each field without typing, because many sites validate the moment you leave a field.
  5. Checks every message and every red field: whether the message is connected to the field, and whether the field announces its error.

It types no values, sends no real data and never goes past the first screen of a form.


What you will see in the report ​

The titles appear in English, as the tool produces them.

"Errors not getting announced on the fields" ​

The main issue. The message exists on screen, but the screen reader does not read it when the user reaches the field.

The screen reader does not announce the error message when the "Email" field is focused. The error message "This field is required." is visually displayed adjacent to the "Email" field, but there is no programmatic association between the field and the error message.

  • Location / field: the affected control, with its visible name ("Email", "From", "Arrival city").
  • Other occurrences: the other fields on the same page with the same problem. A form with seven unconnected fields is one issue with six occurrences, not seven issues.
  • HTML: the field and the message as they are on the page, so developers know what to touch.
  • How to fix it: connect the message to the field. In practice two small changes: give the message element an identifier (if it has none) and make the field reference it with aria-describedby. The report proposes the exact names and asks to reuse the message that already exists rather than create a new one.

When the field points through aria-describedby at an identifier that does not exist on the page, the report says so ("The field references id(s) [...] but no element with those ids exists").

"Field in error state is not marked as invalid" (Best Practice) ​

The field looks wrong (red) but does not "say" so: it lacks aria-invalid="true", which is what makes the reader announce "invalid entry".

The "Email" field is visually displayed in an error state but does not advertise aria-invalid="true". Screen readers will not announce the field as invalid when it receives focus.

When they come together and when apart ​

When the same fields have both problems you see one issue of the first kind, whose fix also covers aria-invalid. When the fields differ (the unconnected message is on three fields but only two lack aria-invalid, or one of them is a picker button where aria-invalid does not apply), the Best Practice is reported separately with its own fields.


How to check it yourself ​

  1. Open the page with NVDA (or JAWS, or VoiceOver on a Mac).
  2. Press the submit button with every field empty. If the site validates on leaving a field, enter a required field and Tab out without typing.
  3. Tab back into a field that shows a message.
  4. The right outcome is hearing the field name, "invalid entry", and the message text.
  5. If you hear only the field name and "blank", the message is not connected (issue). If you hear the message but not "invalid entry", the error flag is missing (Best Practice).

To confirm in the code: in DevTools the field should have aria-describedby (or aria-errormessage) pointing at the id of the element that contains the message, and aria-invalid="true" while the error is visible.


What it does not report (and is not a missed issue) ​

If a case falls here, the tool was never going to report it:

  • Form-wide summaries. "Please complete all required fields", "There are 3 errors". They describe the whole form, not one field, and are not assigned to any.
  • Hints that were there before submitting. "Example: dd/mm/yyyy", format hints, and password-strength meters ("weak", "débil").
  • Fields that change "inside" but don't look wrong. A site can mark a field invalid in its code without painting anything red. No visible change, nothing to announce.
  • Invalid flags set from the start. Some sites mark every required field invalid from page load, before anyone touches it. These are ignored until the field is used.
  • Messages that are already connected, even when the identifier sits on the container around the text, or the message lives inside the field's label. The reader announces them anyway.
  • Fields the user cannot reach: hidden, in an inactive tab or in a closed modal.
  • The browser's own validation bubble. When the site lets Chrome show its own notice ("Please fill out this field"), there is no message on the page to connect; nothing is reported unless the site also paints the field.
  • Messages that only exist while the field has focus (floating bubbles that vanish when you leave). They are not treated as the field's message today; the scope for these cases is still being decided.

Where it cannot reach ​

  • Forms inside iframes (chats, embedded booking widgets from another domain) and inside shadow DOM (for example Shopify Forms newsletter blocks). The tool does not go in there.
  • Sites that block robots (a verification page with a 403 error). The test never starts.
  • Submit buttons that only work after a prior step (accepting terms, a captcha). Then only what the site validates on leaving a field is seen.
  • Custom pickers (city, date) built from buttons instead of fields. They are recognised as the field in error only when they are painted red or indicate that they open a picker.
  • Pages with very many forms. There is a time limit per page and per form; what cannot be reviewed in time is left out and noted in the run log.

Sites already validated ​

Expected results today on some of the sites used in the QA rounds. Use them as a reference: if one of these gives something else, it is worth a look.

SiteWhat it hasExpected result
cuba.cu (footer contact form)unconnected messages; only the e-mail flags its error1 issue + 2 occurrences; 1 Best Practice + 1 occurrence
tricot.cl (sign-up)connected messages, fields without the error flag1 Best Practice + 6 occurrences
abc.cl (sign-in)messages connected through their container1 Best Practice + 2 occurrences
cruzverde.cl (sign-up)nine fields validated on leaving1 issue + 7 occurrences
theinnovators.networkserver-side validation with a loading state1 issue (consent checkbox)
byd.com/ukmessages with an entry animation1 issue + 7 occurrences
royaltonresorts.comonly the checkboxes look wrong1 Best Practice + 1 occurrence
singaporeair.com (flight search)city picker button and one message for two dates1 issue + 2 occurrences; 1 Best Practice + 1 occurrence
caribbean-airlines.com (search)widget with no real form1 issue + 1 occurrence (From, To)
skyairline.com (search)read-only fields in red, no message1 Best Practice + 2 occurrences
airastana.com (search)only a form-wide summary0 issues
idea.davison.com, semrush.comcorrect flags; password-strength meter0 issues

Out of reach (agreed on the ticket): tarjetacencosud.cl (the whole page is an iframe from another domain), fashionspark.com (newsletter in shadow DOM), servefirst.co.uk (HubSpot form in an iframe).


For the technical team ​

  • Test name in the catalogue: form_error_association_async (Screen Reader category).
  • Every rule in detail, the internal steps, configuration variables and diagnostics are on the technical page in the repository: Important Documentation/WCAG CP/1.3.1 - Info and Relationships/form-error-association-test.md.
  • Development ticket and QA rounds: a11y-issue-detector #1425.

WCAG reference ​

Success Criterion 1.3.1 Info and Relationships (Level A), with 3.3.1 Error Identification (Level A) as the companion criterion for the message itself.