FormApi: onSubmit/onServer error cleared on any non-matching validation cause, not just 'change'
Nobody has claimed this yet.
- 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
- Create a form with an
onSubmitvalidator on a field. - Submit without satisfying the validator so
errorMap.onSubmitgets set. - Blur the field (or trigger any
mount/server/dynamicvalidation) without changing its value. form.state.errorMap.onSubmitis 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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