{"record":{"id":"f38dd23efc5c3f63","repo":"marmelab/react-admin","slug":"simpleformiterator-can-only-be-called-within-an-it","errorCode":null,"errorMessage":"SimpleFormIterator can only be called within an iterator input like ArrayInput","messagePattern":"SimpleFormIterator can only be called within an iterator input like ArrayInput","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/ra-core/src/controller/input/SimpleFormIteratorBase.tsx","lineNumber":22,"sourceCode":"import { useWrappedSource } from '../../core/useWrappedSource';\nimport type { RaRecord } from '../../types';\nimport { useEvent } from '../../util';\nimport { useArrayInput } from './useArrayInput';\nimport { SimpleFormIteratorContext } from './SimpleFormIteratorContext';\n\nconst DefaultGetItemDefaults = item => item;\n\nexport const SimpleFormIteratorBase = (props: SimpleFormIteratorBaseProps) => {\n    const {\n        children,\n        getItemDefaults: getItemDefaultsProp = DefaultGetItemDefaults,\n        disableAutoFocus = false,\n    } = props;\n    const getItemDefaults = useEvent(getItemDefaultsProp);\n\n    const finalSource = useWrappedSource('');\n    if (!finalSource) {\n        throw new Error(\n            'SimpleFormIterator can only be called within an iterator input like ArrayInput'\n        );\n    }\n\n    const { append, fields, move, remove } = useArrayInput(props);\n    const { trigger, getValues } = useFormContext();\n\n    const removeField = useEvent((index: number) => {\n        remove(index);\n        const isScalarArray = getValues(finalSource).every(\n            (value: any) => typeof value !== 'object'\n        );\n        if (isScalarArray) {\n            // Trigger validation on the Array to avoid ghost errors.\n            // Otherwise, validation errors on removed fields might still be displayed\n            trigger(finalSource);\n        }\n    });","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/marmelab/react-admin/blob/051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0/packages/ra-core/src/controller/input/SimpleFormIteratorBase.tsx#L4-L40","documentation":"SimpleFormIteratorBase manages the rows of an array field; it discovers the field source via useWrappedSource(''), which is only populated inside an iterator context (ArrayInput). If the resolved source is empty it means the component is not inside an ArrayInput, so row operations (append/remove/move) have no target and react-admin throws.","triggerScenarios":"Rendering <SimpleFormIterator> outside <ArrayInput> (e.g. inside a regular TextInput, in a custom form section, or directly in a Show view); using it as a generic repeater without the array input wrapper.","commonSituations":"Reusing the iterator UI for ad-hoc repeatable fields; nesting mistakes where the iterator is placed under a different input component; tests rendering SimpleFormIterator standalone.","solutions":["Wrap it in <ArrayInput source=\"items\"><SimpleFormIterator>...</SimpleFormIterator></ArrayInput>","For a generic repeater outside react-admin forms, use react-hook-form's useFieldArray directly","In tests, render inside a full <Form><ArrayInput> structure"],"exampleFix":"// before\n<TextInput source=\"title\" />\n<SimpleFormIterator>\n  <TextInput source=\"name\" />\n</SimpleFormIterator>\n// after\n<ArrayInput source=\"items\">\n  <SimpleFormIterator>\n    <TextInput source=\"name\" />\n  </SimpleFormIterator>\n</ArrayInput>","handlingStrategy":"validation","validationCode":"const src = useWrappedSource('');\nif (!src) throw new Error('Must be inside ArrayInput');","typeGuard":"const inArrayInput = (s: string | undefined): s is string =>\n  !!s && s.length > 0;","tryCatchPattern":"try {\n  render(<Form><SimpleFormIterator><TextInput source=\"name\"/></SimpleFormIterator></Form>);\n} catch (e) { logAndFallback(e); }","preventionTips":["Always wrap in <ArrayInput source=...]>","Never use as generic repeater","Assert wrapped source in custom wrappers","Isolated tests for array forms"],"tags":["react-admin","react-context","array-input","form"],"backgroundTag":"hook-used-outside-provider","analyzedSha":"051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0","analyzedAt":"2026-08-30T02:28:14.926Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}