Error summaries
Where the summary goes on a failed submit, what it contains, where focus lands, and why the summary is not a substitute for the inline message.
When to use
Use an error summary whenever a submit fails and more than one thing could be wrong. That is any form with more than one field, and also any single-field form whose failure came from the server rather than the client.
The summary exists for one reason: after a failed submit, a reader who cannot see the whole page has no way to find out what went wrong or where. Scattering inline errors down the form solves the reading problem for someone scanning it visually and solves nothing at all for anyone else.
When not to use
- A single field failed validation on blur. That is an inline error, not a summary, and no summary should appear before submit. See Validation timing.
- The failure is not per-field. "We couldn't reach the server" is not an error summary; it is a form-level error message with a retry, and putting it in a list of field errors makes the reader hunt for a field that is fine.
- The form is one question on its own page. With one question and one error, the inline message plus focus on the field is enough. A summary listing one item is ceremony. See Question pages.
- You want the wiring. Mapping server errors back onto controls is Handbook → Forms.
How it works
flowchart TD
A["Reader submits"] --> B{"Any errors?"}
B -->|"no"| C["Proceed"]
B -->|"yes"| D["Render the summary above the form, in the DOM before it"]
D --> E["Move focus to the summary container"]
E --> F["Each entry links to its field by id"]
F --> G["Activating an entry moves focus to that control"]
G --> H["Fixing the field clears its inline error and its summary entry"]
H --> I{"Any errors left?"}
I -->|"yes"| J["Summary stays, re-rendered, focus not stolen"]
I -->|"no"| K["Summary removed and its removal announced"]The non-negotiable parts:
- The summary is the first thing in the form, in the DOM. Not visually first and DOM-last. Not in a toast in the corner.
- Focus moves to the summary on failure. This is the one place in form design where moving focus is correct, because the reader has just taken an action and the result of that action is here.
- Every entry is a link to the field, using the control's
idas the fragment. Activating it focuses the control, not the label. - Entries are in DOM order, matching the order the reader will meet the fields. Ordering by severity makes the list unfindable.
- Inline errors stay. The summary is additional, never a replacement. A reader who has jumped to field four needs the message there too.
- The summary updates without stealing focus again. Re-focusing on every keystroke traps the reader in the summary.
- Server errors join the same summary. A field rejected server-side appears in the list exactly like a client-side failure; the reader should not have to learn two error systems.
The count is a fact, not a scolding
Give the number ("There is a problem" / "There are 3 problems") because it tells a reader how much work is ahead. Do not add a tone: "Oops! You made 3 mistakes" turns a form failure into a personal one. That is worse than unhelpful in a health context, where the form may be about a symptom the reader is worried about.
Content
Do
Heading: "There are 2 problems". Entries: "Enter your date of birth" and "Enter a weight between 20 and 400 kg". Each entry says what to do.
Don’t
Heading: "Form validation failed". Entries: "dob: required", "weight: out of range". Field names and validator names leaking into the UI.
Do
An entry whose text is identical to the inline message at the field, so the reader recognises it when they arrive.
Don’t
A short entry in the summary and a different, longer message at the field, so the reader has to work out whether these are the same problem.
Wording rules are owned by Error and empty messages.
Accessibility
- The summary is a container with a heading, and focus moves to that
container. Give it
tabindex="-1"so it can receive programmatic focus without entering the tab order. - Announcement follows naturally from focus. Moving focus to a heading and its list is more reliable across screen readers than relying on a live region for content that also changes layout.
- Entries are real links, not buttons styled as links, so the reader uses a mechanism they already know. Activating an entry lands them at the target.
aria-invalidandaria-describedbyare set on every failing control, so the message is available on arrival regardless of how the reader got there.- Do not use
role="alert"on the summary while also moving focus. The duplicate announcement is a common and confusing artefact. - Removal is announced. When the last error clears, a polite status message (WCAG 2.2 SC 4.1.3) confirms it; otherwise a screen-reader user has no way to know the summary is gone.
- WCAG 2.2 SC 3.3.1 and 3.3.3 are the floor: the error is identified in text, and where the correction is knowable it is suggested.
Research
Updates to this page
Last read through against the system on 2026-09-20. Due for review every 12 months; expiry is reported by pnpm run check:freshness.
Validation timing
When a check should run. Why validating on every keystroke is both the most common choice and the worst one for the readers who most need help.
Required and optional
Mark one or the other but never both. In a health product, prefer marking optional, because it makes the cost of every required field visible.