After failure the submit control must be usable again
Aliases: unlock submit · stuck disabled button · restore submit
What it is
After the control is shut to block a double send, this request may fail, time out, or be cancelled—and the same intent still needs to go out once more. Restoring submit means: once failure is certain, the primary button and Enter become activatable again, copy returns from “Submitting” to the submit verb, and focus returns to a usable control or the first error. A successful request should not restore the control to invite a second send. A failed request that does not restore locks people on a dead form. This entry is about how the failure path opens the door, not how the first click closes it.
Why it happens
Disable is a lock on this attempt, not a lock on the rest of the form’s life. Failure ends the attempt: network error, 4xx validation, 5xx, user cancel. If the lock remains, the interface claims “submitting” while no request is in flight; the person’s model and the system state split. A second layer is that failure type decides where restore lands. A transport failure should leave the control in place and explain “it did not send; you can try again.” A business-validation failure should restore the control but take people to the errors, so restore does not become “press again and hit the same wall.” Success stays closed and moves to the result. The worst mid-state is every failure leaving the button spinning: cannot edit, cannot leave. Timeouts are especially good at leaving this lock, because no callback arrives and the client thinks the request is still flying.
Studying it
Create a dropped network, a 422 validation failure, a 500, and a user cancel. Watch when the control restores, whether copy returns to the verb, and where focus is.
Independent variables: failure type, whether a timeout ceiling exists, whether cancel aborts the request. Dependent variables: whether the control is pressable once failure is certain, delay from failure to being able to resubmit, times stuck in “Submitting” with no exit, whether the first resubmit after restore carries the same unfixed error.
Mocks that return instantly in the lab never show a hung timeout. Add a request that never returns. Do not count “automatic retry after failure” as restore—the control stays shut during retries; restore happens after retries are abandoned.
Where it stops holding
Payments and orders in an unknown state are not certain failures. The control must not casually restore to invite another order; query instead of resubmit. After partial success (attachment uploaded, record not created) say which parts must not be sent again before restoring. Failures from being signed out will only fail again if submit is restored; send people to sign-in. Offline, the control may restore so people can edit, but the real send should enter a queue labeled “will send when back online,” not masquerade as another immediate submit.
Applying it
- Put a timeout on submit. Timeout, network error, an explicit failure response, and user cancel must all restore the control to activatable and drop in-progress copy.
- On validation failure: restore the control and take people to the errors; do not only light the button so they hit the wall again.
- On success or “accepted, processing”: keep the control shut and move to the result or to progress. Do not light it again for symmetry.
- Verify by submitting with the network dropped: after a few seconds the button must read “Submit” and be pressable. On 422 it must be pressable with focus on the first error. Use a never-returning request and confirm timeout does not leave “Submitting” forever. On payment, an unknown state must not restore the button to “pay again.”