TanStack / TanStack/form

Pre-reset field validation completion clears a newer validation status

Open
#2,384 0 comments 0 reactions 0 assignees View on GitHub

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

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
  1. Start validation A via a field's onChangeAsync and leave its promise pending.
  2. Call form.reset().
  3. Blur the field to start validation B via onBlurAsync and leave B pending.
  4. Resolve A.
  5. 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.

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 with packages/form-core/tests/FieldApi.spec.ts around the linked tests, then read FieldApi.validateAsync and the reset handling for _pendingValidationsCount. Run the provided Vitest command with Node 24.8.0 and pnpm. Done means both reset cases preserve isValidating until the newer validation settles, while the no-reset overlap controls continue to pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend, testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.