TanStack / TanStack/form

Form-level validator doesn't re-run after first submit while fields hold errors — bug or by design?

Open
#2,248 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

With a form-level onSubmit validator only (no field-level validators) and the default validation logic:

The first submit runs the validator and populates all field errors.
After that, canSubmit is false (since submissionAttempts > 0 and isValid === false), so every subsequent submit hits the guard at the top of _handleSubmit and returns early — no further validation runs until the user has cleared all outstanding errors.
That part I understand is likely intended (button-disable pattern). My real question is about the next layer:

The specific question
When I set canSubmitWhenInvalid: true to allow re-submitting while invalid, the form-level validator still doesn't re-run. Tracing _handleSubmit:

await this.validateAllFields("submit");     // field-level only; no-op when I have no field validators
if (!this.state.isFieldsValid) return;       // <-- bails here because stale field errors remain
await this.validate("submit");               // <-- form-level schema; never reached

Because we only have a form-level validator, validateAllFields can't clear or recompute anything, so isFieldsValid stays false from the previous submit, and validate("submit") (the call that re-runs the form schema) is skipped.

Is this intended? Specifically: should validateAllFields returning stale field errors prevent the form-level validator from re-running on submit? It means a form configured with only a form-level validator can never re-validate on a second submit while any error is outstanding.

Your minimal, reproducible example

see below

Steps to reproduce
const form = useForm({
  defaultValues: { name: '', other: '' },
  validators: {
    onSubmit: ({ value }) => {
      const errors = {};
      if (!value.name) errors.name = 'Required';
      if (!value.other) errors.other = 'Required';
      return Object.keys(errors).length ? { fields: errors } : undefined;
    },
  },
  canSubmitWhenInvalid: true,
});
  1. submit empty -> both fields error
  2. type into name, clear it (error clears on change)
  3. submit again -> name error does NOT return; other still errors
Expected behavior

On each submit, the form-level validator re-runs and reflects the current values (so name would error again in step 3).

How often does this bug happen?

None

Screenshots or Videos

No response

Platform

macOS, chrome

TanStack Form adapter

None

TanStack Form version

v1.29.1

TypeScript version

v^6.0.3

Additional context

No response

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 by tracing _handleSubmit, validateAllFields("submit"), and validate("submit") in the form implementation, then reproduce the reported sequence with the provided useForm example. Check the existing validation tests and add coverage for a second submit with stale field errors; done means the behavior is documented by a passing regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.