{"record":{"id":"924bc558acfde155","repo":"payloadcms/payload","slug":"hierarchy-parent-field-parentfieldname-in-col","errorCode":null,"errorMessage":"Hierarchy parent field \"${parentFieldName}\" in collection \"${collectionConfig.slug}\" must be a relationship field","messagePattern":"Hierarchy parent field \"(.+?)\" in collection \"(.+?)\" must be a relationship field","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/payload/src/hierarchy/sanitizeHierarchyCollection.ts","lineNumber":56,"sourceCode":"  const defaultParentFieldName = getHierarchyFieldName(collectionConfig.slug)\n\n  if (collectionConfig.hierarchy === true) {\n    collectionConfig.hierarchy = {\n      parentFieldName: defaultParentFieldName,\n    }\n  }\n\n  const parentFieldName = collectionConfig.hierarchy.parentFieldName ?? defaultParentFieldName\n\n  // Check if parent field already exists\n  const existingParentField = collectionConfig.fields.find(\n    (field) => fieldAffectsData(field) && field.name === parentFieldName,\n  )\n\n  if (existingParentField) {\n    // Validate existing parent field configuration\n    if (existingParentField.type !== 'relationship') {\n      throw new Error(\n        `Hierarchy parent field \"${parentFieldName}\" in collection \"${collectionConfig.slug}\" must be a relationship field`,\n      )\n    }\n\n    if (existingParentField.hasMany !== false) {\n      throw new Error(\n        `Hierarchy parent field \"${parentFieldName}\" in collection \"${collectionConfig.slug}\" must have hasMany set to false`,\n      )\n    }\n\n    if (existingParentField.localized === true) {\n      throw new Error(\n        `Hierarchy parent field \"${parentFieldName}\" in collection \"${collectionConfig.slug}\" cannot be localized. The parent relationship must be consistent across all locales.`,\n      )\n    }\n  } else {\n    // Auto-create parent field if it doesn't exist\n    // useHeaderButton defaults to true - parent selection via header button with miller columns","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/hierarchy/sanitizeHierarchyCollection.ts#L38-L74","documentation":"Thrown at config-sanitisation time by sanitizeHierarchyCollection when a collection declares hierarchy and an existing field with the resolved parentFieldName is present but is not of type 'relationship'. The parent link must be a relationship to the same collection, so a mismatched type blocks boot.","triggerScenarios":"Defining hierarchy: true on a collection that already has a field named the default parent field name (e.g. _parent) of type text/array/group, or naming hierarchy.parentFieldName after an existing non-relationship field.","commonSituations":"Enabling hierarchy on a collection that previously used that field name for another purpose; colliding with an auto-generated parent field name after a rename.","solutions":["Change the existing field's type to relationship (hasMany:false) pointing at the same collection.","Rename the conflicting field, or set hierarchy.parentFieldName to a fresh unused name so Payload auto-creates it.","Remove the conflicting field if it is unused.","After fixing, re-init Payload to re-run sanitisation."],"exampleFix":"// before\nexport const Pages = { slug: 'pages', fields: [\n  { name: 'parent', type: 'text' },\n], hierarchy: true }\n\n// after\nexport const Pages = { slug: 'pages', fields: [\n  { name: 'parent', type: 'relationship', relationTo: 'pages', hasMany: false },\n], hierarchy: true }","handlingStrategy":"validation","validationCode":"// at config build time\nconst existing = collectionConfig.fields.find(\n  (f) => fieldAffectsData(f) && f.name === parentFieldName,\n)\nif (existing && existing.type !== 'relationship') {\n  throw new Error(`Field ${parentFieldName} must be a relationship`)\n}","typeGuard":"import type { RelationshipField } from 'payload'\nfunction isRelationship(f: any): f is RelationshipField {\n  return f?.type === 'relationship'\n}","tryCatchPattern":null,"preventionTips":["Run payload.init() in a smoke test as part of CI to catch config errors early.","Let hierarchy auto-create the parent field by using an unused parentFieldName."],"tags":["hierarchy","config","sanitization","fields","relationship"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}