Ask a coding agent to test the failed submission before accepting a new form. A person who corrects one field should not have to reconstruct every valid answer. A person whose request may already have arrived should not be told to submit again without a way to resolve that uncertainty. Both are ordinary events, and a form that handles neither has passed only the demo.
The practical acceptance question is whether the user can finish after something goes wrong. The six cases below give the agent a focused recovery test plan; passing the happy path alone does not answer it. This guide sets out the cases and the state each one should leave the user in, what the W3C’s form guidance does and does not require, why a lost response is not a rejection, the fixes that make recovery worse, and the exercise to hand the agent so the evidence is something a reviewer can replay.
- 01Keep valid work.Correcting one error should not erase unrelated answers in the same process. Re-entry is a cost the form imposes, not a security feature.
- 02Explain the next action.Give a specific field correction or a meaningful status, not only a red banner. The person needs to know what went wrong and where to fix it.
- 03Resolve uncertain outcomes.A lost response does not establish that the server rejected the submission. Offering a fresh submit button at that moment manufactures duplicates.
- 04Test recovery as a journey, not a message.A case passes when the person can proceed and the destination agrees with what the screen told them. The message alone proves neither.
01 — The QuestionThe happy path is not the acceptance test
A coding agent asked to build a form may build only the path where everything works, test that path, and report success. That is the path it was described. The failures arrive later, from users who typed a space in a phone number, lost signal in a lift, or left the tab open until their session expired. Each of those people is at the exact moment they are most likely to give up, and the form’s behavior in that moment is the product.
So the acceptance test has to be phrased around failure. Not “does the form submit?” but “after each of these six things goes wrong, can the person still finish, and does the record they end up with match what the screen told them?” Phrased that way, the agent can build toward it and a reviewer can replay it. Phrased as “good error handling”, neither can.
“Starting from a filled form, trigger each failure in the table, then show me the person completing the submission without re-entering unrelated fields, and show me the destination record.” One sentence, six runs, and the agent knows exactly what finished looks like.
02 — The MatrixSpecify the recovery state for each failure
Run these cases in an authorized test environment using identifiable test data. The expected states are design recommendations; adapt them to the form’s sensitivity and destination semantics. A case is not passed until the user can proceed and the destination agrees with the message, which means every row has two checks: one on the screen and one in the system behind it.
The cases run roughly from the most to the least visible. A missing required field announces itself; a lost response after sending looks, from the user’s chair, identical to a slow network. The later rows are where agents most need the table, because nothing in the happy path hints that they exist.
| Failure case | User should retain or see | Acceptance check |
|---|---|---|
| Missing required field | Valid answers plus a specific correction | Correct the missing value and finish without re-entering unrelated fields. |
| Server rejects a value | Submitted values and the server’s relevant error | Fix the rejected field; verify the revised payload. |
| Connection fails before sending | Recoverable input and a clear unsent state when known | Restore connectivity and submit the preserved values. |
| Response is lost after sending | Input or receipt context plus an unresolved status | Inspect the operation before offering a potentially duplicate attempt. |
| Login expires during entry | A stated route to reconnect and recover permitted work | Verify what can be preserved and what must be entered again. |
| One part of a multi-step submission fails | Completed and incomplete parts identified separately | Resume only the unresolved part under the application’s contract. |
03 — The MessageMake the error useful to the person reading it
W3C’s form-notification guidance recommends clear feedback about submission results, including helpful error-resolution instructions. It covers overall feedback and feedback near the affected controls. Those are distinct needs: the person must know something went wrong and where to correct it, and a banner at the top of a long form answers the first without the second.
Give the agent an observable requirement. Instead of “improve error handling,” ask it to preserve valid fields, identify the rejected input and verify that the correction can be reached by keyboard. A visible message without a usable correction path is incomplete. An illustrative pass: the message names the field, focus moves to it or a link does, and the field’s own hint says what a valid value looks like. An illustrative fail: a red border and nothing else.
Keep technical details out of the primary message unless they help the user decide. A request identifier can support a help conversation; a stack trace usually cannot. Preserve diagnostic details in the appropriate test evidence rather than exposing them as the user’s next step.
Near the control
The rejected field is marked, named in text, and carries the correction hint. Focus can reach it directly from the summary. This is the part a visual-only check misses when the error is announced by color alone.
At the top
One sentence saying the submission did not complete and how many fields need attention, linking to the first. Necessary on a long form; insufficient on its own.
In the evidence
The request identifier, the server’s raw error and the timestamp go in logs and in the test record. They support a help conversation; they are not the person’s next step.
04 — The InputRetain useful input without promising permanent storage
W3C’s explanation of WCAG 2.2 redundant entry describes reuse of previously entered information in the same process. It includes exceptions for essential re-entry, security and information that is no longer valid. It does not require storage between sessions, and a team that reads it as “save everything forever” has taken on a storage, access and expiry problem the criterion never asked for.
For the acceptance test, distinguish correcting a field in the current process from returning days later. Preserve valid work through the former where appropriate. If the product promises a saved draft across sessions, that is an additional feature with its own storage, access and expiry behavior to verify, and it belongs in its own acceptance case rather than being smuggled in as “recovery”.
Do not solve every recovery problem by putting the whole form into persistent browser storage. Decide which values may be retained, where and for how long. Test the chosen behavior, including sign-out and shared-device use when those are relevant to the application: a form that helpfully restores a previous visitor’s medical details on a library computer has solved the wrong problem.
05 — The UnknownDo not confuse missing confirmation with rejection
A server can accept a request even if the browser loses the response. In that case, immediately presenting a fresh submit action can create a duplicate if the backend has no protection. Keep the result unresolved until the application can look up the operation or safely repeat it under its documented contract. The honest state of the form at that moment is “we do not know yet”, and the interface should say so rather than guess in either direction.
If the application cannot resolve the submission automatically, show an unresolved status and a support route tied to that operation. The AI tool-error reference explains why unknown outcomes need inspection. Apply the same distinction to the form’s user-facing state without exposing internal jargon: the user sees “we are checking whether your request arrived”, the log sees the request identifier and the lookup.
This is a row agents can easily build wrong, because the natural implementation of “the request failed” is to re-enable the button. A disabled button is a courtesy; a lookup by request identifier, or an idempotency key the server honors, is the control.
06 — The FailuresFour fixes that make recovery worse
Each of the illustrative patterns below is a reasonable-sounding response to one row of the table that breaks another row. They are easy to fall into because each one is what “handle errors better” means if you only have one failure in mind.
The reload reset: on any error the form reloads to a clean state, which clears the invalid value and every valid one with it. The eager retry: a lost response re-enables Submit with a “try again” hint, and the second attempt lands on a server that already saved the first. The everything-draft: to stop re-entry, the whole form is written to persistent storage on every keystroke, including the card number, with no expiry and no sign-out hook. The silent partial: in a multi-step submission the first step succeeds, the second fails, and the form reports failure for both, so the user re-does step one and creates a duplicate record there.
Each is caught by running the whole matrix rather than the one case that prompted the fix. The reload reset fails row one; the eager retry fails row four; the everything-draft fails the sign-out check in section 04; the silent partial fails row six.
After every fix, run all six cases again, not just the one that was broken. Recovery behaviors interact: the state a form keeps for one failure is the state it can leak or duplicate in another.
07 — The ExerciseGive the coding agent a complete recovery exercise
Start with a filled form containing representative valid values. Trigger one specific failure, record what remains, then complete the correction and check the destination. Repeat for the relevant failure cases. Keep the test identifiers so the reviewer can distinguish an old record from the new result; a destination with two records and no way to tell which run made which has proved nothing about duplicates.
Use keyboard interaction to check focus and correction, and the rendered page to inspect message clarity. The two checks catch different defects: a message can be clear and unreachable, or reachable and useless.
If the exercise reveals a defect, use the coding-agent bug-report guide to preserve reproduction steps. For evidence attached to the fix, use the screenshot evidence reference, and for the accessibility of the error states themselves, our guide to verifying AI accessibility fixes covers the keyboard and announcement checks. Teams that want the matrix built into their form acceptance rather than remembered per project can work with our AI transformation practice.
08 — DecisionA form is finished when a person can recover
Accept the recovery path as part of the form.
Keep valid input, explain the specific correction and resolve uncertain submissions before another attempt. The form is ready when a person can recover from each of the six cases and the destination state supports the result shown on screen.
For implementation support, explore our AI transformation services.