{"record":{"id":"bff20dec19710a9e","repo":"octobercms/october","slug":"nestedform-must-specify-either-a-form-property-f","errorCode":null,"errorMessage":"NestedForm must specify either a \"form\" property for the form fields","messagePattern":"NestedForm must specify either a \"form\" property for the form fields","errorType":"exception","errorClass":"SystemException","httpStatus":null,"severity":"error","filePath":"modules/tailor/contentfields/NestedFormField.php","lineNumber":40,"sourceCode":"    public $fieldsetConfig;\n\n    /**\n     * defineConfig will process the field configuration.\n     */\n    public function defineConfig(array $config)\n    {\n        if (isset($config['form'])) {\n            $this->fieldsetConfig = (array) $config['form'];\n        }\n    }\n\n    /**\n     * validateConfig\n     */\n    public function validateConfig()\n    {\n        if ($this->fieldsetConfig === null) {\n            throw new SystemException('NestedForm must specify either a \"form\" property for the form fields');\n        }\n    }\n\n    /**\n     * defineFormField will define how a field is displayed in a form.\n     */\n    public function defineFormField(FormElement $form, $context = null)\n    {\n        $form->addFormField($this->fieldName, $this->label)->defaultCreate()->useConfig($this->getCleanFormConfig());\n    }\n\n    /**\n     * defineBatchListColumn\n     */\n    public function defineBatchListColumn(ListElement $list, $context = null)\n    {\n        $list->defineColumn($this->fieldName, $this->label);\n    }","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/tailor/contentfields/NestedFormField.php#L22-L58","documentation":"NestedFormField builds its nested fieldset solely from the `form:` key of the field config (the constructor only assigns fieldsetConfig when isset($config['form'])). validateConfig() requires a non-null fieldsetConfig, so a nestedform field without a `form:` block — nothing to render or extend into the model — throws a SystemException.","triggerScenarios":"A field `{type: nestedform}` is defined with no `form:` key, or `form:` is present but empty/unparsed so isset() fails or the value doesn't reach the constructor. Validation runs when Tailor compiles the blueprint fieldset.","commonSituations":"Expecting nestedform to work like a partial without config; YAML indentation placing `form` under the wrong level; a `form:` value that parses to null; fieldsets imported from other projects missing the form block.","solutions":["Add a `form:` block containing a `fields:` map under the nestedform field.","Check indentation so `form:` is a direct child of the field and actually contains fields.","If you only need a single level of nested fields without form nesting, use a regular field group instead."],"exampleFix":"# before\nfields:\n  address:\n    label: Address\n    type: nestedform\n\n# after\nfields:\n  address:\n    label: Address\n    type: nestedform\n    form:\n      fields:\n        street:\n          type: text\n        city:\n          type: text","handlingStrategy":"validation","validationCode":"$fieldConfig = $blueprintContent['fields'][$fieldName] ?? [];\nif (($fieldConfig['type'] ?? '') === 'nestedform' && !isset($fieldConfig['form'])) {\n    throw new InvalidArgumentException(\"nestedform field '{$fieldName}' requires a form: block.\");\n}","typeGuard":"function hasFormBlock(array $fieldConfig): bool\n{\n    return isset($fieldConfig['form']) && is_array($fieldConfig['form']);\n}","tryCatchPattern":"try {\n    // blueprint validation / tailor:refresh\n} catch (\\SystemException $e) {\n    // add form: { fields: { ... } } under the nestedform field and revalidate\n}","preventionTips":["Author nestedform fields from a snippet that already includes a form.fields skeleton.","Validate blueprint YAML structure in CI before deploy."],"tags":["tailor","nestedform","field-config","blueprint"],"backgroundTag":"missing-required-config","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}