Design Principle
Form errors are not one red component; they combine field contracts, state machines, and recovery paths, and should route to narrower guidance for summaries, accessible feedback, persistent labels, and transactional recovery.
Large Theory
A form error state contract aligns frontend implementation with interaction design. A healthy form does more than show errors below fields; it knows each field's label, hint, required/optional copy, input purpose, validation source, trigger timing, error anchor, submit state, server-failure branch, and mobile keyboard behavior. This entry is a router: for ordinary field feedback, use accessible-form-feedback; for long-form top summaries, use error-summary-pattern; for high-trust failed submits and preserved input, use transactional-form-error-recovery; for label, hint, and placeholder boundaries, use form-label-persistence; for flow splitting and drafts, use form-flow-and-validation.
Small Points
- Field contracts come before visual styling: every input needs visible label, helper, error, required/optional text, default value, format rule, server rule, autocomplete, inputMode, and submit owner.
- Validation timing follows risk: untouched empty required fields usually validate on submit or continue; format errors may appear after blur; input-time feedback stays lightweight; async username, promo-code, and address checks are debounced and cancelable.
- Do not disable submit only because the form has not been validated; users need a way to trigger validation and see what to fix. During submission, prevent duplicates while showing validating/submitting state and a retry path after failure.
- Set
aria-invalidonly when a field is actually invalid; connect error messages, hints, and descriptions througharia-describedbyor clear anchors. Usearia-errormessageonly when the error message is visible and the field is invalid. - An error summary does not replace inline errors. In long forms, multi-error states, or large scroll distances, the top summary provides navigation while field errors provide the repair instruction.
- Group errors belong to fieldset/legend, group hints/errors, and the first editable control, not only to a red border around an outer div.
- Server errors need recoverable and fatal branches: recoverable errors preserve input, explain cause, and provide retry or edit paths; fatal errors explain system, permission, or network state and the next support route.
- Mobile error states must check keyboard appearance, fixed bottom submit bars, sticky headers, auto-scroll, enterKeyHint, and 44px targets so error text is not hidden.
Design Judgment
A form is implementable when the agent can produce a field list, validation timing table, error summary structure, ARIA/focus wiring, submit state matrix, mobile input attributes, and server-failure branches. Red borders, toast-only feedback, disabled buttons, or browser-native prompts are signs that the contract is missing.
Implementation Notes
Define FormFieldContract: id, name, label, helper, requiredText, inputType, inputMode, autocomplete, valueState, validationTrigger, validationRules, errorId, describedByIds, ariaInvalid, serverErrorPolicy, mobileKeyboard, and focusTarget. Define FormSubmitState: idle, dirty, validating, submitting, success, recoverableError, and fatalError. In React, field components should not own all error copy; the form layer manages error summaries, focus movement, duplicate-submit prevention, and server-response mapping.
Counterexamples/Risks
A permanently disabled submit button with no explanation, error on every keystroke, toast-only errors, aria-invalid true on initial render, summary links that do not reach fields, field groups with no legend, server failure that clears input, mobile bottom bars covering errors, and payment or identity failures with no retry or support path.
Case Study
GOV.UK's validation pattern treats error handling as a set of coordinated behaviors: show the form again with entered values, add an error prefix to the page title, show a top summary, show field-level errors, turn off HTML5 validation, and still validate on the server. NHS error summary guidance adds healthcare context by linking each summary item to the affected answer and showing matching field errors. WCAG Error Identification requires textual identification of errors; W3C ARIA21, MDN aria-invalid, aria-describedby, and aria-errormessage define frontend wiring boundaries. Baymard's checkout research says inline validation can reduce effort, but premature validation creates friction; NN/g classifies validation messages as user-input-related error feedback. The reusable lesson is that form error design manages state, semantics, location, and timing together.
Source Links
GOV.UK Validation pattern: https://design-system.service.gov.uk/patterns/validation/ GOV.UK Error summary: https://design-system.service.gov.uk/components/error-summary/ NHS Error summary: https://service-manual.nhs.uk/design-system/components/error-summary WCAG Error Identification: https://www.w3.org/WAI/WCAG22/Understanding/error-identification.html W3C ARIA21: https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA21 MDN aria-invalid: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-invalid MDN aria-describedby: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-describedby MDN aria-errormessage: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-errormessage NN/g form validation messages: https://www.nngroup.com/articles/indicators-validations-notifications/ Baymard inline validation: https://baymard.com/blog/inline-form-validation
Agent Directive
Create the field contract and submit state machine before choosing error summaries, inline errors, ARIA/focus wiring, mobile keyboard behavior, and server-failure branches; route to accessible-form-feedback, error-summary-pattern, transactional-form-error-recovery, form-label-persistence, and form-flow-and-validation when needed.