{"record":{"id":"8be2d492c71718ca","repo":"payloadcms/payload","slug":"collection-hierarchyslug-is-not-a-hierarchy","errorCode":null,"errorMessage":"Collection \"${hierarchySlug}\" is not a hierarchy","messagePattern":"Collection \"(.+?)\" is not a hierarchy","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/utilities/getHierarchyAncestry.ts","lineNumber":41,"sourceCode":" */\nexport async function getHierarchyAncestry({\n  hierarchySlug,\n  ids,\n  payload,\n  user,\n}: GetHierarchyAncestryArgs): Promise<HierarchyAncestryResult> {\n  if (ids.length === 0) {\n    return { items: [] }\n  }\n\n  const collectionConfig = payload.collections[hierarchySlug]?.config\n  const hierarchyConfig =\n    collectionConfig?.hierarchy && typeof collectionConfig.hierarchy === 'object'\n      ? collectionConfig.hierarchy\n      : undefined\n\n  if (!hierarchyConfig) {\n    throw new Error(`Collection \"${hierarchySlug}\" is not a hierarchy`)\n  }\n\n  const parentFieldName = hierarchyConfig.parentFieldName\n  const useAsTitle = collectionConfig.admin?.useAsTitle || 'id'\n\n  // Cache for already-fetched items to avoid redundant queries\n  const itemCache = new Map<number | string, Record<string, unknown>>()\n\n  const fetchItem = async (id: number | string): Promise<null | Record<string, unknown>> => {\n    const cached = itemCache.get(id)\n    if (cached) {\n      return cached\n    }\n\n    try {\n      const item = await payload.findByID({\n        id,\n        collection: hierarchySlug,","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/ui/src/utilities/getHierarchyAncestry.ts#L23-L59","documentation":"Thrown by getHierarchyAncestry when the collection at `hierarchySlug` has no `hierarchy` config object (or it is not a plain object). The ancestry walker needs the hierarchy config - specifically `parentFieldName` - to traverse the parent chain and build breadcrumb paths; without it the operation is undefined.","triggerScenarios":"Calling getHierarchyAncestry with the slug of a normal (non-hierarchy) collection; referencing a hierarchy collection after its `hierarchy` config was removed; a typo in hierarchySlug; custom code assuming any collection with a parent field is a hierarchy.","commonSituations":"Disabling hierarchy on a collection without updating callers, slug renames that orphan ancestry callsites, custom navigation/breadcrumb code that does not check hierarchy presence first.","solutions":["Ensure the collection config declares `hierarchy: { parentFieldName, ... }` as an object.","Only call getHierarchyAncestry for collections where `config.hierarchy` is an object.","Guard callers (navigation, breadcrumbs) with a hierarchy-presence check before invoking.","If the hierarchy was intentionally removed, delete the now-dead ancestry callsite."],"exampleFix":"// before: 'tags' has no hierarchy config\ngetHierarchyAncestry({ hierarchySlug: 'tags', ids, payload })\n\n// after: declare hierarchy on the collection\n// export const Tags = {\n//   slug: 'tags',\n//   hierarchy: { parentFieldName: 'parent' },\n//   fields: [{ name: 'parent', type: 'relationship', relationTo: 'tags' }],\n// }","handlingStrategy":"type-guard","validationCode":"const cfg = payload.collections[hierarchySlug]?.config\nif (!cfg?.hierarchy || typeof cfg.hierarchy !== 'object') {\n  // 'hierarchySlug' is not a hierarchy - skip the ancestry call\n}","typeGuard":"function isHierarchyCollection(\n  cfg: unknown,\n): cfg is { hierarchy: Record<string, unknown> } {\n  return (\n    !!cfg &&\n    typeof cfg === 'object' &&\n    'hierarchy' in cfg &&\n    typeof (cfg as { hierarchy: unknown }).hierarchy === 'object' &&\n    (cfg as { hierarchy: unknown }).hierarchy !== null\n  )\n}\n\n// usage:\n// if (isHierarchyCollection(payload.collections[hierarchySlug]?.config)) {\n//   await getHierarchyAncestry({ hierarchySlug, ids, payload })\n// }","tryCatchPattern":null,"preventionTips":["Centralize a hierarchy-presence check and run it before any hierarchy utility.","Derive the set of hierarchy slugs from config once and reuse it across all callers.","When removing hierarchy from a collection, grep for its slug in ancestry/breadcrumb callsites and delete them."],"tags":["hierarchy","config","validation"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}