TanStack / TanStack/form

FormApi: onSubmit/onServer error cleared on any non-matching validation cause, not just 'change'

Open Beginner friendly
#2,295 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

v1 v2: needs investigation
Dominant language
TypeScript
Stars
6.7k
Forks
682
Avg merge
5d 18h
Merged PRs (30d)
7

Description

Describe the bug

FormApi's sync validation has the same bug that #2211 is fixing at the field level, just one level up. In packages/form-core/src/FormApi.ts, the block that's supposed to clear a stale onSubmit error "as soon as the user enters a valid value" checks cause !== 'submit' instead of cause === 'change':

const submitErrKey = getErrorMapKey('submit')
if (
  this.state.errorMap?.[submitErrKey] &&
  cause !== 'submit' &&
  !hasErrored
) {
  this.baseStore.setState((prev) => ({
    ...prev,
    errorMap: { ...prev.errorMap, [submitErrKey]: undefined },
  }))
}

ValidationCause is 'change' | 'blur' | 'submit' | 'mount' | 'server' | 'dynamic', so this clears the submit error on blur, mount, server, and dynamic validation runs too, not just when the user actually changes a value. The comment right above it says the intent is "clear the error as soon as the user enters a valid value in the field", which only 'change' represents.

The exact same block exists again a few lines down for onServer errors, with the same shape (cause !== 'server'), so it has the analogous problem: a server-side error can get cleared by a blur or an unrelated dynamic revalidation instead of only by the user actually changing the value.

I think this is what #1472 was really running into. That issue was closed as a React Native Web quirk (RNW fires a blur event on submit, and blurOnSubmit={false} was suggested as the workaround), but the underlying reason blur clears the error at all is this condition, so the same symptom is reachable on plain web too, any blur on a field with an existing submit error clears it, RNW's extra blur-on-submit event just makes it show up immediately and consistently.

Your minimal, reproducible example

Not a runnable repro since this is internal form-core logic, but here's the sequence that reaches the bug directly through the public API:

const form = new FormApi({ defaultValues: { name: '' } })
form.mount()

const field = new FieldApi({
  form,
  name: 'name',
  validators: { onSubmit: ({ value }) => (value.length > 0 ? undefined : 'required') },
})
field.mount()

await form.handleSubmit() // form.state.errorMap.onSubmit is now set

field.handleBlur() // no value change, just a blur
// form.state.errorMap.onSubmit is cleared here, even though nothing was fixed
Steps to reproduce
  1. Create a form with an onSubmit validator on a field.
  2. Submit without satisfying the validator so errorMap.onSubmit gets set.
  3. Blur the field (or trigger any mount/server/dynamic validation) without changing its value.
  4. form.state.errorMap.onSubmit is cleared, even though the underlying problem wasn't fixed.
Expected behavior

The submit-level error should only clear when the cause is 'change', matching the comment's stated intent and consistent with how #2211 is fixing the identical check at the field level.

Platform

n/a (form-core logic, framework-agnostic)

TanStack Form version

current main, packages/form-core/src/FormApi.ts

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/form-core/src/FormApi.ts and run the supplied FormApi/FieldApi sequence, checking the submit and server error-clearing blocks during blur and other validation causes. Done when submit and server errors remain until a value change, while the existing submit validation behavior still works.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.