skip to content

Once a field displays an error, what must the form do so the message disappears on the keystroke that fixes the value?

level: middleimportance: should knowfreq 56%

answer

  1. the message must be able to die
  2. clear eagerly, raise lazily
  3. re-check on change while an error stands
  4. derived verdict beats stored message

basics

~20 s

Re-run that field's rule on every change while an error is standing, and clear the message as soon as the rule passes. Waiting for the next blur or submit leaves a stale error on an already-correct value.

solid answer

~50 s

The rule that raised the error has to run again on each change, and the display has to be driven by the fresh verdict rather than by a stored message. Concretely: on the change event, re-check the field; if it now passes, drop the error immediately; if it still fails, keep the existing message and do not swap in a different one mid-word. This is the clearing half of **reward early, punish late** - raising errors late, at blur or submit, but clearing them as early as possible. A form that re-validates only on blur keeps telling the user their password is too short while they look at a long enough password, which reads as broken. The switch is usually per field and conditional: validate on change *only while that field has an error*, so correct fields are still not nagged mid-typing.

go deeper

for a junior

Know the expectation: when you correct a field, its error should vanish immediately. That requires the rule to run again on the edit, not at the next blur.

for a middle

Explain the asymmetry - clear on change, raise on blur or submit - and why the error must be derived from the current verdict rather than stored from a past one.

for a senior

Talk through the cases that break it in real forms: dependent rules, checks that need a round trip, normalisation mismatches, and server-sourced messages that no local rule can re-evaluate.

for a principal

Make it a reviewable convention: one escalation policy per field, one message at a time in a fixed priority order, and errors modelled as derivations so that no code path can forget to clear one.

A standing error on a value that has already been fixed is one of the most damaging small defects a form can have. The user did what the message asked, the message did not move, so the message is now lying. The fix is a timing rule, not a copy rule. ## The mechanism Three things have to be true: 1. **The rule re-runs on change** for the field that currently has an error. Not on blur, not at the next submit - on the edit itself. 2. **The displayed message is derived from the current verdict**, not a string stored when the error was first raised. If the error is stored, something must explicitly delete it; if it is derived, it disappears on its own when the rule passes. 3. **The display gate stays open** for that field. It was opened by blur or by the submit attempt, and it must not swing shut and hide the fact that the field is now fine - clearing the error is what communicates success. ## Why per-field and conditional Turning on per-change validation for the whole form would punish every field mid-typing, which is what blur-based timing was avoiding. So the usual policy is a per-field escalation: - A field starts in the polite mode: its rule judges at blur, and at submit. - Once it has a visible error, that field also re-checks on every change. - When the error clears, the field can drop back to the polite mode, so a later half-typed value is not judged again. This is why a failed submit is such a natural escalation point: it marks exactly the set of fields the user is now repairing, and those are the fields that benefit from per-keystroke checking. | Policy while an error stands | What the user sees | |---|---| | Re-check on change, clear on pass | Message vanishes on the keystroke that fixes it | | Re-check on blur only | Message persists over an already-correct value until focus leaves | | Re-check at submit only | Message persists until the next send attempt, inviting a re-submit to find out | | Re-check on change, but message stored and never deleted | Message persists regardless of the verdict - the worst of the four | ## Do not upgrade the error while they type Re-validating per keystroke tempts a form into changing the message on every edit: too short, then invalid character, then too short again. A message that mutates mid-word is harder to act on than a stale one. Two conventions keep it calm: - **Report one rule at a time per field**, in a fixed priority order, so the user works through them deterministically. - **Do not raise a new error on a change**; only clear or keep the existing one. New verdicts wait for the next blur or submit. The clearing direction is the only one that is safe to run eagerly, which is precisely what *reward early, punish late* encodes. ## Edge cases worth naming - **Rules that depend on other fields.** When a field's verdict depends on another field's value, fixing the other field must also re-run this one's rule, otherwise the error sits on a pair that now agrees. - **Rules that are not instant.** A check that has to ask a server cannot clear on the same keystroke; it needs a pending state, and a debounce, so the message does not flicker between old error and new verdict. - **Normalisation.** If the rule judges a normalised form of the value (trimmed, case-folded, separators stripped) but the message was raised against the raw input, the two can disagree about whether the value is now acceptable. Judge the same form you will send. - **Errors that did not come from a local rule.** A message produced by a server response describes the value that was sent. The moment the user edits that value, the message is about history; most forms clear such an error on the first change to the field, because the client has no way to re-check it locally. - **Batch verdicts.** A form that recomputes all rules on any change must still only *show* the ones whose fields are eligible, or fixing one field can reveal messages on fields the user has not reached yet. ## What the framework gives you The wiring differs by reactivity model, the behaviour should not. Where errors are derived values computed from the field's current value, clearing is automatic - nothing has to remember to delete a message. Where errors are stored in a form-level structure and mutated by handlers, clearing is a deliberate write, and the omission of that write is the bug. When reviewing a form, that is the first thing to look for: is the error a *derivation* of the value, or a *record* of a past judgment? The second shape needs an explicit clear on every path, including the one where the value becomes valid again.

  • Why clear errors on change but not raise new ones on change?
    Because the two directions have different costs. Clearing early is always welcome: it confirms the fix at the moment it happens. Raising early accuses a value the user is still composing, since half-typed input is legitimately not valid yet. Raising therefore waits for a deliberate signal - leaving the field, or attempting to submit - while clearing runs on every edit.
  • An error raised from the server's response sits on a field the user has now edited. What should happen to it?
    Clear it on the first change to that field. The message described the value that was sent, and the client cannot re-check it locally, so keeping it would assert something about a value the server never saw. The field returns to its local rules, and the next submit produces a fresh server verdict if one is still warranted.
  • Why can a standing error survive even though the rule is re-running correctly on every change?
    Because the message is stored rather than derived. The rule produces a passing verdict, but nothing deletes the string that was written when it first failed, so the display keeps rendering history. Either derive the message from the current verdict, or make every re-check path explicitly remove a message that no longer applies.

A smoke alarm that keeps sounding after the window is open teaches people to rip the battery out. Clearing has to be as quick as raising.

saying these in an interview costs you the question

  • Leaves an error visible until the next blur or submit
  • Stores the error message and never deletes it on a pass
  • Switches the whole form to per-change validation to fix one field
  • Rewrites the message on every keystroke while the user types
  • Forgets that fixing a partner field must re-run a dependent rule
  • Judges the raw input but submits a normalised value