{"record":{"id":"12f92a9cdc49c475","repo":"octobercms/october","slug":"field-name-is-reserved-fieldname","errorCode":null,"errorMessage":"Field name is reserved: {$fieldName}.","messagePattern":"Field name is reserved: (.+?)\\.","errorType":"exception","errorClass":"BlueprintException","httpStatus":null,"severity":"error","filePath":"modules/tailor/classes/BlueprintVerifier.php","lineNumber":238,"sourceCode":"            }\n        }\n\n        // Validate source references from raw config (before fieldset expansion)\n        $this->validateSourceReferences($blueprint, $fields);\n\n        $fieldset = FieldManager::instance()->makeFieldset(['fields' => $fields]);\n        $fieldset->validate();\n\n        // Check invalid and reserved field names\n        foreach ($fieldset->getAllFields() as $fieldName => $fieldObj) {\n            if (!preg_match('/^[a-zA-Z0-9\\_]+$/', $fieldName)) {\n                $lineNo = $this->findLineFromKeyValPair($blueprint->content, $fieldName, '');\n                throw new BlueprintException($blueprint, \"Invalid field name: {$fieldName}.\", $lineNo);\n            }\n\n            if (in_array($fieldName, $this->reservedFieldNames)) {\n                $lineNo = $this->findLineFromKeyValPair($blueprint->content, $fieldName, '');\n                throw new BlueprintException($blueprint, \"Field name is reserved: {$fieldName}.\", $lineNo);\n            }\n        }\n    }\n\n    /**\n     * validateSourceReferences validates source references in raw field config recursively\n     */\n    protected function validateSourceReferences(Blueprint $blueprint, array $fields)\n    {\n        foreach ($fields as $fieldName => $fieldConfig) {\n            if (!is_array($fieldConfig)) {\n                continue;\n            }\n\n            // Check source at this level\n            $source = $fieldConfig['source'] ?? null;\n            if ($source && !$this->sourceExists($source)) {\n                $lineNo = $this->findLineFromKeyValPair($blueprint->content, 'source', $source);","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/tailor/classes/BlueprintVerifier.php#L220-L256","documentation":"Tailor reserves certain field names because they collide with columns, attributes and relations that generated content models always define — `attributes`, `site_id`, `site_root_id`, `created_user_id`, `relation_id`, `field_name`, `nest_left`, `nest_right`, `blueprint_uuid`, `primary_id`, `content_group`, `primaryRecord`, and more. The verifier rejects any field on that list (mirrored in SchemaBuilder::$reservedFieldNames), including fields arriving through imported fieldsets.","triggerScenarios":"A blueprint field is named exactly `attributes`, `site_id`, `content_group`, `primaryRecord`, or another reserved entry; or a shared fieldset imported with `import:` contains one of those names and gets expanded by getAllFields().","commonSituations":"Naming a field after internal columns (e.g. `site_id` for a site picker, `attributes` for a generic fieldset); fieldsets written before a name became reserved in a newer October build; content_group used for navigation grouping.","solutions":["Rename the field to a non-reserved name, e.g. `site` instead of `site_id`.","Check the full reserved list in Tailor\\Classes\\BlueprintVerifier::{$reservedFieldNames} (duplicated in Tailor\\Classes\\SchemaBuilder) and avoid every entry.","If the field comes from an imported fieldset, fix it in that fieldset file — the verifier checks the expanded field list."],"exampleFix":"# before\nfields:\n  attributes:\n    label: Attributes\n    type: text\n\n# after\nfields:\n  product_attributes:\n    label: Attributes\n    type: text","handlingStrategy":"validation","validationCode":"$reserved = (new \\ReflectionClass(\\Tailor\\Classes\\BlueprintVerifier::class))\n    ->getDefaultProperties()['reservedFieldNames'];\nforeach ($fields as $name => $config) {\n    if (in_array($name, $reserved)) {\n        throw new InvalidArgumentException(\"Reserved field name: {$name}\");\n    }\n}","typeGuard":"function isReservedTailorFieldName(string $name): bool\n{\n    static $reserved;\n    $reserved = $reserved ?? (new \\ReflectionClass(\\Tailor\\Classes\\BlueprintVerifier::class))\n        ->getDefaultProperties()['reservedFieldNames'];\n    return in_array($name, $reserved, true);\n}","tryCatchPattern":"try {\n    // blueprint scan\n} catch (\\Tailor\\Classes\\BlueprintException $e) {\n    // message names the reserved field; rename it in the blueprint or imported fieldset\n}","preventionTips":["Keep a checklist of reserved names (read from the BlueprintVerifier reservedFieldNames property) during content modeling reviews.","Avoid naming fields after database-sounding concepts (site_id, relation_id, nest_left, attributes).","Re-run tailor:refresh after October upgrades — new reserved names may have been added."],"tags":["tailor","reserved-names","blueprint","validation"],"backgroundTag":"reserved-name-collision","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}