Describe the bug
A field validation started before form.reset() can clear the validation status of a newer run when the older run finishes. A UI reading field.state.meta.isValidating can stop displaying its checking indicator while the new validation is still pending.
This is a follow-up to the review discussion on #2382. The counter race reproduces on that PR's base as well as its head; it is separate from the stale-error fix in #2381/#2382.
Your minimal, reproducible example
Tests-only commit with unchanged main production code
git clone https://github.com/lunaxislu/form.git
cd form
git checkout ba6de4a83142fafcb74d5763f7e6574067019b14
# Use Node 24.8.0 from .nvmrc and pnpm via Corepack.
corepack pnpm install --frozen-lockfile
corepack pnpm --dir packages/form-core exec vitest run tests/FieldApi.spec.ts -t 'should preserve pending validation when an older run settles'
The four cases use deferred promises and fake timers. The two reset cases fail; the two no-reset controls pass. Both direct and linked-field validation are covered.
Steps to reproduce
- Start validation A via a field's
onChangeAsync and leave its promise pending.
- Call
form.reset().
- Blur the field to start validation B via
onBlurAsync and leave B pending.
- Resolve A.
- Observe that the field's
isValidating becomes false even though B is pending.
A starts count=1, isValidating=true
reset count=0, isValidating=false
B starts count=1, isValidating=true
A settles count=0, isValidating=false <-- B is still pending
B settles count=0, isValidating=false
Using different validation causes avoids the same-cause debounce timer issue tracked by #2372/#2373. The linked-field variant starts A by changing another field listed in onChangeListenTo.
Expected behavior
After reset, a completion belonging to a pre-reset run should not decrement the new run's counter. field.state.meta.isValidating should remain true until B settles. Without reset, overlapping runs should still decrement normally (2 → 1 → 0).
How often does this bug happen?
Every time with the controlled ordering above.
Platform
macOS; reproduced in the form-core Vitest suite with jsdom, without a browser UI or server dependency.
TanStack Form adapter
vanilla (@tanstack/form-core)
TanStack Form version
1.33.5, main source at 57a855b42b9b99cee5ca12890b70c7df84e2982c.
TypeScript version
5.9.3
Additional context
Reset replaces field metadata, including _pendingValidationsCount. The outer completion block of FieldApi.validateAsync still calls endValidation() against current metadata without distinguishing a pre-reset run. This applies to the main field and linked fields.
The report concerns completion accounting across a full form reset. It does not request changes to debounce scheduling, per-field reset, or form/group-level validation. Searches for reset/counter/isValidating and related reports did not reveal a separate report for this exact sequence beyond the #2382 review discussion.
Describe the bug
A field validation started before
form.reset()can clear the validation status of a newer run when the older run finishes. A UI readingfield.state.meta.isValidatingcan stop displaying its checking indicator while the new validation is still pending.This is a follow-up to the review discussion on #2382. The counter race reproduces on that PR's base as well as its head; it is separate from the stale-error fix in #2381/#2382.
Your minimal, reproducible example
Tests-only commit with unchanged main production code
The four cases use deferred promises and fake timers. The two reset cases fail; the two no-reset controls pass. Both direct and linked-field validation are covered.
Steps to reproduce
onChangeAsyncand leave its promise pending.form.reset().onBlurAsyncand leave B pending.isValidatingbecomes false even though B is pending.Using different validation causes avoids the same-cause debounce timer issue tracked by #2372/#2373. The linked-field variant starts A by changing another field listed in
onChangeListenTo.Expected behavior
After reset, a completion belonging to a pre-reset run should not decrement the new run's counter.
field.state.meta.isValidatingshould remain true until B settles. Without reset, overlapping runs should still decrement normally (2 → 1 → 0).How often does this bug happen?
Every time with the controlled ordering above.
Platform
macOS; reproduced in the form-core Vitest suite with jsdom, without a browser UI or server dependency.
TanStack Form adapter
vanilla (
@tanstack/form-core)TanStack Form version
1.33.5, main source at
57a855b42b9b99cee5ca12890b70c7df84e2982c.TypeScript version
5.9.3
Additional context
Reset replaces field metadata, including
_pendingValidationsCount. The outer completion block ofFieldApi.validateAsyncstill callsendValidation()against current metadata without distinguishing a pre-reset run. This applies to the main field and linked fields.The report concerns completion accounting across a full form reset. It does not request changes to debounce scheduling, per-field reset, or form/group-level validation. Searches for reset/counter/isValidating and related reports did not reveal a separate report for this exact sequence beyond the #2382 review discussion.