Repository navigation
Description
Describe the bug
Calling form.setFieldValue() on a field with no mounted FieldApi creates field metadata with an errorMap but no errorSourceMap:
// FormApi.setFieldValue
this.setFieldMeta(field, (prev) => ({
...prev, // prev is undefined for an unmounted field
isTouched: true,
isDirty: true,
errorMap: { ...prev?.errorMap, onMount: undefined },
}))Later, a FormGroup validator may report an error for that field. When this happens, FormGroupApi.distributeFieldErrors finds the existing metadata and accesses errorSourceMap without guarding against it being undefined:
const isPreviousErrorFromFormValidator =
fieldMeta?.errorSourceMap[errorMapKey] === 'form'The optional chaining guards fieldMeta, but not errorSourceMap. This throws:
TypeError: Cannot read properties of undefined (reading 'onChange')
The exception aborts the operation that triggered validation, such as a handleChange call in an event handler.
This is related to TanStack/form#2231 and TanStack/form#2233, but covers a different case. PR #2233 handles metadata that is entirely missing by using prev = defaultFieldMeta. In this case, the metadata exists, but setFieldValue has left it incomplete.
Your minimal, reproducible example
https://codesandbox.io/p/sandbox/aged-butterfly-mq9p43
Steps to reproduce
Environment: @tanstack/form-core 1.33.5, reproduced in CodeSandbox using a React template, on Chrome 155.0.8059.80 / macOS (arm64).
The reproduction uses only @tanstack/form-core APIs. React is used only to render the button and display the result.
import { FieldApi, FormApi, FormGroupApi } from '@tanstack/form-core'
const form = new FormApi({
defaultValues: {
launch: {
type: 'manual',
price: undefined,
},
},
})
form.mount()
// Step-level group validator:
// price is required only when type is "exclusive".
const group = new FormGroupApi({
form,
name: 'launch',
validators: {
onChange: ({ value }) =>
value.type === 'exclusive' && value.price === undefined
? { fields: { price: 'Price is required' } }
: undefined,
},
})
group.mount()
const typeField = new FieldApi({
form,
name: 'launch.type',
})
typeField.mount()
// launch.price has no mounted field yet.
// It renders only when the type is "exclusive".
form.setFieldValue('launch.price', undefined)
console.log(form.getFieldMeta('launch.price'))
// Metadata exists, but errorSourceMap is missing.
typeField.handleChange('exclusive')
// TypeError: Cannot read properties of undefined (reading 'onChange')The stack trace includes:
FormGroupApi.distributeFieldErrors
validateFieldOrGroupFn
FormGroupApi.validateSync
FieldApi.validate
FieldApi.setValue
FieldApi.handleChange
Without this line, handleChange('exclusive') succeeds:
form.setFieldValue('launch.price', undefined)Expected behavior
handleChange('exclusive') succeeds, and the group validation error is assigned to launch.price, just as it is when the field has never been written to.
How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
- OS: macOS (Apple Silicon / arm64)
- Browser: Chrome
- Version: 155.0.8059.80 (Official Build)
- Environment: CodeSandbox (React)
- @tanstack/form-core: 1.33.5
TanStack Form adapter
react-form
TanStack Form version
1.33.5
TypeScript version
No response
Additional context
No response
Activity