Skip to content

removeValue on array field incorrectly sets isTouched=true on all shifted siblings #2131

@ntatoud

Description

@ntatoud

Describe the bug

Calling form.removeValue(index) on an array field flips isTouched to true on every sibling at index ≥ removed index. Even when the user has never interacted with those fields.

The bug lives in @tanstack/form-core, so every adapter (react, vue, solid, svelte, angular, lit) is affected.

Your minimal, reproducible example

https://github.com/ntatoud/repro-tanstack-form-removevalue-touched.git

Steps to reproduce

  1. git clone https://github.com/ntatoud/repro-tanstack-form-removevalue-touched.git
  2. npm install && npm run test (deterministic vitest assertion)
  3. npm run dev
  4. Click 'remove index 2' button.
  5. Notice how all shifted elements are not marked as touched.

Expected behavior

isTouched stays false on every remaining item: The user never touched anything.

values  = ['a', 'b', 'd', 'e']
touched = [false, false, false, false]

How often does this bug happen?

Every time

Screenshots or Videos

Enregistrement.de.l.ecran.2026-04-16.a.22.33.10.mov

Platform

  • OS: macOS 26.2
  • Node: 24.15.0
  • Browser: any (not related to browser)

TanStack Form adapter

react-form

TanStack Form version

1.29.0

TypeScript version

6.0.2

Additional context

Adapter-agnostic: bug is in form-core, not the React bindings

Proposed fix

In validateArrayFieldsStartingFrom, bypass validateField when the field already has a mounted instance and call fieldInstance.validate(cause) directly. This preserves validation, skipping the auto-touch:

// packages/form-core/src/FormApi.ts
batch(() => {
  fieldsToValidate.forEach((nestedField) => {
    fieldValidationPromises.push(
      Promise.resolve().then(() => {
        const fieldInstance = this.fieldInfo[nestedField]?.instance
        if (fieldInstance) {
          return fieldInstance.validate(cause)
        }
        return this.validateField(nestedField, cause)
      }),
    )
  })
})

Verified locally by patching node_modules/@tanstack/form-core/dist/esm/FormApi.js.

The same fix likely applies to swapFieldValues / moveFieldValues / insertFieldValue if they call validateArrayFieldsStartingFrom (worth auditing as a follow-up)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions