Skip to content

Error Messages

DodaTech 3 min read

title: "Error Messages — Announcing Errors with aria-describedby and aria-invalid" description: "Learn how to display accessible error messages using aria-describedby for descriptions and aria-invalid to mark fields with errors for screen reader users." weight: 7 date: 2026-06-28 lastmod: 2026-06-28 tags: [accessibility, forms]


Error messages must be programmatically associated with their form controls using aria-describedby, and fields in error must be marked with aria-invalid so screen readers announce the problem.

## What You'll Learn

How to associate error messages with form controls, mark invalid fields, and announce errors dynamically using live regions.

## Why It Matters

Users who cannot see the screen must know which field has an error and what the error is. A red border alone is invisible to screen readers.

## Real-World Use

A user submits a form with an invalid email. The screen reader hears "Email address, invalid data, edit, Please enter a valid email address" because the error is properly associated via aria-describedby.

## Error Association

```html
<label for="email">Email address</label>
<input type="email" id="email" name="email"
       aria-describedby="email-error"
       aria-invalid="true">
<p id="email-error" role="alert">Please enter a valid email address</p>

Dynamic Error Injection with JavaScript

const emailInput = document.getElementById('email');
const errorContainer = document.getElementById('email-error');

emailInput.addEventListener('blur', function() {
  if (!this.validity.valid) {
    this.setAttribute('aria-invalid', 'true');
    errorContainer.textContent = this.validationMessage || 'Invalid email format';
  } else {
    this.setAttribute('aria-invalid', 'false');
    errorContainer.textContent = '';
  }
});

Summary Error List

<div id="form-errors" role="alert" aria-live="assertive">
  <h2>Please correct the following errors:</h2>
  <ul>
    <li><a href="#email">Email address is required</a></li>
    <li><a href="#password">Password must be at least 8 characters</a></li>
  </ul>
</div>

Common Mistakes

1. Using color or icon alone for errors

Color-blind users cannot see red borders. Screen readers do not announce visual changes.

2. Error message not associated with field

Without aria-describedby, screen reader users do not know which field the error belongs to.

3. Removing error without updating aria-invalid

When the user fixes the error, set aria-invalid back to "false" and clear the error message.

4. Errors inside the label

Error text inside a label becomes part of the accessible name, which is confusing.

5. Not setting focus to the first error

After validation, move focus to the first field with an error so the user can immediately correct it.

Practice Questions

1. What ARIA attribute marks a field as containing invalid data? aria-invalid="true" indicates the field has a validation error.

2. How do you associate an error message with a form control? Use aria-describedby on the input pointing to the id of the error message element.

3. What role should the error container have? role="alert" ensures the error message is announced immediately when it appears.

Challenge: Build a form with three fields. Add client-side validation that displays error messages using aria-describedby and marks invalid fields with aria-invalid.

FAQ

What is the difference between aria-describedby and aria-labelledby?

aria-labelledby provides the accessible name (replacing the label). aria-describedby provides additional description (supplementing the name).

Should errors appear inline or in a summary?

Both. Inline errors next to each field help users identify the specific problem. A summary at the top provides an overview for screen reader users.

Does role=alert work on page load?

No, role=alert only announces dynamic content changes. For errors on page load, use role=alert on a container that is initially empty and gets populated.

Can I use aria-errormessage instead?

Yes, aria-errormessage is specifically designed for error associations, but support is less reliable than aria-describedby.

How do I announce errors without moving focus?

Use aria-live=assertive on the error container so the error is announced when it appears, even if focus is elsewhere.

Mini Project

Add error handling to a registration form. Each field should show an inline error on blur if invalid. A summary error list should appear at the top on submit. All errors must be associated using aria-describedby.

What's Next

Now learn Inline Validation patterns that provide real-time feedback as users type.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro