When form validation fails, screen reader users must know three things: that an error occurred, which field is affected, and how to correct it. Displaying a red border or showing text only visually is invisible to AT. Without aria-invalid and aria-describedby wiring the error message to the input, screen reader users hear only the field name repeated—no indication that anything is wrong. WCAG 2.2 SC 3.3.1 (Level A) requires errors to be identified in text, and SC 3.3.3 (Level AA) requires suggestions for correction. Section 508 2018 Refresh 502.3.6 covers form field associations. Every form submission failure that goes unannounced to screen reader users silently breaks a user journey.
Medium because inaccessible error messages impair form completion for screen reader users but do not prevent them from eventually reaching the correct field through sequential navigation.
Wire error messages to their inputs using aria-invalid and aria-describedby, and use role="alert" or aria-live="polite" to announce errors on insertion. In your form components:
const [emailError, setEmailError] = useState('');
<div>
<label htmlFor="email">Email address</label>
<input
id="email"
type="email"
aria-invalid={emailError ? 'true' : 'false'}
aria-describedby={emailError ? 'email-error' : undefined}
/>
{emailError && (
<div id="email-error" role="alert" className="error-text">
{emailError}
</div>
)}
</div>
Error messages must be actionable—"Email must contain an @ symbol" not "Invalid email". Set focus to the first errored field after submission to orient keyboard users.
ID: gov-section-508.keyboard-assistive.error-messages
Severity: medium
What to look for: Count all relevant instances and enumerate each. Check all form inputs for validation. When a form field has an error, verify that: (1) the error message is visually associated with the field, (2) the error message is announced to screen readers via aria-describedby or aria-invalid, (3) the error message explains what's wrong and how to fix it (not just "Invalid input").
Pass criteria: Every form input with an error has an associated error message visible both visually and to screen readers. At least 1 implementation must be verified. Error messages are descriptive (e.g., "Email must contain @ symbol" not just "Invalid").
Fail criteria: Error messages are displayed only visually (no ARIA association), or error messages are generic and unhelpful.
Skip (N/A) when: No form validation exists.
Detail on fail: Example: "Email validation error displays red text 'Invalid email' below the field but does not use aria-describedby to announce it to screen readers. Password field shows 'Password must be 8+ characters' but only as a red outline, with no associated error message element."
Remediation: Associate error messages with form fields:
const [emailError, setEmailError] = useState('');
<input
id="email"
type="email"
aria-invalid={emailError ? 'true' : 'false'}
aria-describedby={emailError ? 'email-error' : undefined}
/>
{emailError && <div id="email-error" role="alert">{emailError}</div>}
Use role="alert" or aria-live="polite" to announce errors when they appear:
<div id="email-error" role="alert" aria-live="polite">
Email must contain an @ symbol
</div>
Cross-reference: For related patterns and deeper analysis, see the corresponding checks in other AuditBuffet audits covering this domain.