WCAG 3.3.3: Error Suggestion
When a form rejects an entry and you already know how to fix it, you must suggest the correction in text. This Level AA criterion turns "invalid date" into "enter the date as DD/MM/YYYY" — the difference between a user who recovers in seconds and one who abandons the task. The one exception: don't suggest a fix when it would compromise security or defeat the purpose of the content.
The success criterion, in full
If an input error is automatically detected and suggestions for correction are known, then the suggestions are provided to the user, unless it would jeopardize the security or purpose of the content.
Why error suggestion matters
Knowing that a field is wrong is only half the battle. The user still has to work out howto fix it — and if your message stops at "invalid", they are left guessing. Did the date need slashes or dashes? Is the phone number too long or too short? Should the amount include the currency symbol? Each guess is another failed submit, and on a checkout or an application that friction is exactly where people give up.
Error suggestion removes the guesswork. It is especially decisive for people with cognitive and learning disabilities, for whom a vague error is a hard stop, and for screen reader users who cannot glance around the form for clues. A suggested correction is also a plain usability win — fewer support tickets, fewer abandoned forms, and higher completion rates for everyone. Because the suggestion is just better-written error text, it is one of the cheapest Level AA wins available.
What 3.3.3 actually requires
The criterion turns on three conditions. When all three hold, a suggestion is mandatory at Level AA.
1. An input error is detected
The trigger is the same as 3.3.1 — a problem your code can catch.
3.3.3 only applies once an input error has been automatically detected: a required field left blank, an email without an @, a date outside the allowed range, a postcode in the wrong format. If your code cannot tell that something is wrong, the criterion does not ask you to invent a suggestion.
2. You know a suggestion for correction
If the fix is knowable, you must offer it.
When the cause of the error is something your application can determine — the field is required, the format is wrong, the value is out of range, the date does not exist — you must provide that suggestion to the user in text. 'Enter a date in the format DD/MM/YYYY' or 'Password must be at least 12 characters' tells the user not just that something failed but exactly how to put it right.
3. Unless it would jeopardise security or purpose
Security and content purpose come first.
There is one exception: you are not required to suggest a correction if doing so would jeopardise the security or purpose of the content. The classic example is a login form — revealing 'that password is wrong but the username is correct' would leak information to an attacker. A test question is another: suggesting the answer would defeat its purpose. In these cases a generic message is acceptable.
Note: 3.3.3 builds directly on 3.3.1 Error Identification. First identify the field and describe the problem in text (3.3.1, Level A); then, if you know the fix, suggest it (3.3.3, Level AA). You usually deliver both in the same sentence, wired to the field with the same aria-describedby.
The security and purpose exception
3.3.3 has one carve-out: you are not required to suggest a correction if doing so would jeopardise the security or purpose of the content. This is not a loophole for lazy error messages — it is a narrow exception for cases where the suggestion itself would do harm.
Security — sign-in forms
Saying "that password is wrong" while accepting the email confirms which accounts exist, helping attackers enumerate users. Use a single generic message — "Email or password is incorrect" — for both fields. This is both secure and still meets 3.3.1, because the user is told an error exists.
Purpose — tests and quizzes
On an exam, a knowledge check, or a CAPTCHA, suggesting the correct answer would defeat the point of the exercise. Here a generic "incorrect, try again" is acceptable, because the suggestion is exactly what you must withhold.
Outside these specific situations, the exception does not apply. A shipping address, a date of birth, a payment amount, a phone number — none of these are security-sensitive in the way a password is, so for these you must give the user the format, range, or rule they need to succeed.
Writing a good suggestion
A useful suggestion names the rule the value broke and shows what a valid value looks like. Compare:
Identifies but does not suggest
- "Invalid date."
- "Password not accepted."
- "Wrong format."
- "Amount not allowed."
- "Error in this field."
Suggests the correction
- "Enter the date as DD/MM/YYYY, e.g. 14/03/2026."
- "Use at least 12 characters, including a number."
- "Enter a UK postcode, e.g. SW1A 1AA."
- "Enter an amount between £1 and £500."
- "Enter your email, e.g. name@example.com."
When the input is one of a fixed set of values, the strongest suggestion lists or links to the valid options — for example, "We don't ship to that country. Choose from the supported countries list." Keep the wording plain, avoid jargon, and put the suggestion where the error is, so a screen reader announces the problem and the fix together.
Code examples
A field whose error includes the suggested fix
The message both identifies the error (3.3.1) and suggests the correction (3.3.3), tied to the field with aria-describedby.
<label for="dob">Date of birth</label>
<input
type="text"
id="dob"
name="dob"
inputmode="numeric"
autocomplete="bday"
aria-invalid="true"
aria-describedby="dob-hint dob-error"
/>
<!-- Persistent hint helps prevent the error (3.3.2) -->
<p id="dob-hint" class="field-hint">For example, 14/03/1990.</p>
<!-- Error names the problem AND suggests the fix (3.3.1 + 3.3.3) -->
<p id="dob-error" class="field-error">
<span aria-hidden="true">⚠ </span>
That date isn't valid. Enter it as DD/MM/YYYY, for example 14/03/1990.
</p>The security exception on a sign-in form
A single generic message covers both fields, so the form never reveals which accounts exist — meeting 3.3.1 without suggesting a specific fix.
<div role="alert" id="signin-error" class="error-summary">
<p>Email or password is incorrect. Check both and try again.</p>
</div>
<label for="email">Email</label>
<input id="email" type="email" autocomplete="username"
aria-invalid="true" aria-describedby="signin-error" />
<label for="password">Password</label>
<input id="password" type="password" autocomplete="current-password"
aria-invalid="true" aria-describedby="signin-error" />Building a suggestion from the validation rule
Derive the suggestion from the same rule that detected the error, so the message always tells the user how to satisfy it.
function suggestForAmount(value, { min, max }) {
const n = Number(value)
if (value.trim() === "") return `Enter an amount between £${min} and £${max}.`
if (Number.isNaN(n)) return `Enter a number, for example £${min}.`
if (n < min) return `That's below the minimum. Enter at least £${min}.`
if (n > max) return `That's above the maximum. Enter no more than £${max}.`
return null // valid
}Accessible React field that surfaces a suggestion
A reusable field that renders a persistent hint plus an error message containing the suggested correction, and only describes the field with the error id when an error is present.
function Field({ id, label, hint, error, ...props }) {
const hintId = hint ? `${id}-hint` : undefined
const errorId = error ? `${id}-error` : undefined
const describedBy = [hintId, errorId].filter(Boolean).join(" ") || undefined
return (
<div>
<label htmlFor={id}>{label}</label>
<input
id={id}
aria-invalid={error ? true : undefined}
aria-describedby={describedBy}
{...props}
/>
{hint && <p id={hintId} className="field-hint">{hint}</p>}
{error && (
<p id={errorId} className="field-error">
<span aria-hidden="true">⚠ </span>
{/* error string should name the problem and suggest the fix */}
{error}
</p>
)}
</div>
)
}Common mistakes
- Stopping at 'invalid' when your validation knows the exact rule that was broken and could state the fix.
- Showing the required format only as placeholder text that disappears once the user starts typing — it is gone exactly when the error appears.
- Over-applying the security exception to non-sensitive fields like addresses, dates, or amounts to justify vague messages.
- Suggesting a correction on a sign-in form that reveals whether the email or the password was the wrong one.
- Putting the suggestion in a tooltip or a separate panel that is not associated with the field via aria-describedby, so screen readers never announce it.
- Generic catch-all messages ('Something went wrong') for errors whose cause your code already knows.
- Jargon-filled suggestions ('value fails regex pattern') that a non-technical user cannot act on.
- Suggesting a fix that is itself wrong or out of date because the message text drifted from the actual validation rule.
How to test for 3.3.3
- 1
Trigger each kind of error on purpose
For every field, submit a wrong format, an out-of-range value, and a blank required entry. For each, confirm the message not only flags the error but tells you how to put it right.
- 2
Ask: could the code have suggested the fix?
If your validation knows the rule (format, range, required, allowed values), the message should reflect it. A message that says less than the validation knows is a 3.3.3 gap.
- 3
Listen with a screen reader
With NVDA, JAWS, or VoiceOver, move to each invalid field and confirm the suggested correction is announced together with the label and the error — not hidden in a tooltip or detached panel.
- 4
Check the security-sensitive forms
On sign-in, password reset, and similar flows, confirm the messages do not reveal which field was wrong or whether an account exists, while still telling the user an error occurred.
- 5
Verify the suggestion matches the rule
Confirm the wording in the message agrees with the actual validation — if the rule is 12 characters, the suggestion must say 12, not 8. Drift between the two is a common, quiet failure.
Audit a live form with the URL Accessibility Auditor and learn the manual screen reader steps in the Screen Reader Testing Guide.
Related success criteria
3.3.1 Error Identification — A
The Level A foundation: identify which field is wrong and describe the error in text. 3.3.3 adds the suggested fix on top of that description.
3.3.2 Labels or Instructions — A
Prevents errors before they happen with clear labels and format hints. A persistent hint plus a 3.3.3 suggestion is a powerful pairing.
4.1.3 Status Messages — AA
Announces error counts and status through live regions without moving focus, so the user learns suggestions appeared even after an async submit.
3.3.4 Error Prevention (Legal, Financial, Data) — AA
For high-stakes submissions, requires that entries are reversible, checked, or confirmed — the prevention partner to 3.3.3's recovery focus.
Browse every criterion in the WCAG Success Criteria hub or work through the full WCAG 2.2 checklist.
Frequently asked questions
What does WCAG 3.3.3 Error Suggestion require?
WCAG 3.3.3 requires that when an input error is automatically detected and you know how to correct it, you suggest the correction to the user in text — unless doing so would jeopardise the security or purpose of the content. In plain terms: do not just say 'invalid date', say 'Enter a date in the format DD/MM/YYYY'. It is a Level AA success criterion and the natural next step after 3.3.1 Error Identification.
How is 3.3.3 different from 3.3.1 Error Identification?
They are a pair. 3.3.1 Error Identification (Level A) requires you to identify which field is wrong and describe that an error exists, in text. 3.3.3 Error Suggestion (Level AA) goes one step further: when you can work out how to fix the error, you must suggest the fix. 3.3.1 is 'the date is invalid'; 3.3.3 is 'the date is invalid — enter it as DD/MM/YYYY'. A well-written error message usually satisfies both at once, because describing an error clearly almost always implies the correction.
When can I skip suggesting a correction?
Only when suggesting it would jeopardise the security or purpose of the content. On a sign-in form, you should not say 'the password is wrong but the email exists' because that confirms which accounts are valid to an attacker — a generic 'Email or password is incorrect' is the accessible and secure answer. On a quiz or test, suggesting the right answer would defeat the purpose. Outside these narrow cases, if you know the fix, you must offer it.
Does a generic message like 'Invalid input' meet 3.3.3?
Usually not. If your validation knows why the input was rejected — wrong format, out of range, required — then 'Invalid input' withholds a suggestion you are capable of giving, which fails 3.3.3. The message should name the problem and point to the fix: 'Enter an amount between £1 and £500' rather than 'Invalid amount'. A generic message is only acceptable when the security or purpose exception applies, or when your code genuinely cannot determine the cause.
Where should the suggested correction appear?
Put the suggestion in the same text message that identifies the error, and associate it with the field using aria-describedby so a screen reader announces it when the field receives focus. For errors surfaced after submit, include the suggestion in the error summary links too. The suggestion is just well-written error text — it does not need a separate mechanism, only that the words tell the user what to do next and that those words are programmatically connected to the control.
How does 3.3.3 relate to 3.3.4 and 4.1.3?
They are part of the same form-handling family. 3.3.2 Labels or Instructions prevents errors up front. 3.3.1 Error Identification names an error once it happens. 3.3.3 Error Suggestion adds the fix. 3.3.4 Error Prevention (Legal, Financial, Data) requires review, confirmation, or reversal for high-stakes submissions. 4.1.3 Status Messages covers announcing error counts and status via live regions without moving focus. Build all of them together and your forms become genuinely recoverable.