{"record":{"id":"c00059e95e149dec","repo":"payloadcms/payload","slug":"collection-collectionslug-does-not-have-hiera","errorCode":null,"errorMessage":"Collection \"${collectionSlug}\" does not have hierarchy enabled","messagePattern":"Collection \"(.+?)\" does not have hierarchy enabled","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/payload/src/hierarchy/utils/getAncestors.ts","lineNumber":53,"sourceCode":" *\n * Uses request context caching for efficiency when called multiple times.\n */\nexport async function getAncestors({\n  id,\n  collectionSlug,\n  includeSelf = true,\n  req,\n}: GetAncestorsArgs): Promise<Ancestor[]> {\n  const { payload, user } = req\n\n  const collectionConfig = payload.collections[collectionSlug]?.config\n  if (!collectionConfig) {\n    throw new Error(`Collection \"${collectionSlug}\" not found`)\n  }\n\n  const hierarchyConfig = collectionConfig.hierarchy\n  if (!hierarchyConfig) {\n    throw new Error(`Collection \"${collectionSlug}\" does not have hierarchy enabled`)\n  }\n\n  const parentFieldName = hierarchyConfig.parentFieldName\n  const { localized: isTitleLocalized, titleFieldName } = findUseAsTitleField(collectionConfig)\n\n  // Initialize cache if needed\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  const context = req.context as any\n  if (!context.hierarchyAncestorCache) {\n    context.hierarchyAncestorCache = {}\n  }\n  if (!context.hierarchyAncestorCache[collectionSlug]) {\n    context.hierarchyAncestorCache[collectionSlug] = {}\n  }\n\n  const cache = context.hierarchyAncestorCache[collectionSlug]\n  const ancestors: Ancestor[] = []\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/hierarchy/utils/getAncestors.ts#L35-L71","documentation":"Thrown by getAncestors in the hierarchy utilities when the target collection's config has no `hierarchy` block. The function needs `hierarchyConfig.parentFieldName` (and a use-as-title field) to walk the ancestor chain, so a collection without hierarchy enabled cannot resolve ancestors. It is a hard precondition failure, not a data-missing case.","triggerScenarios":"Calling getAncestors({ collectionSlug, req, includeSelf }) where `payload.collections[collectionSlug].config.hierarchy` is undefined. This happens when the slug points to a flat (non-tree) collection, or the hierarchy plugin/field was never added to that collection's config.","commonSituations":"Enabling hierarchy on some collections but calling a generic ancestor helper against the wrong slug; renaming/removing the hierarchy field from a collection but leaving UI or code that still calls getAncestors; copying an ancestor-walking code block to a new collection that was never configured for hierarchy.","solutions":["Add `hierarchy: { parentFieldName: 'parent' }` to the collection's config so the hierarchy block exists.","Verify the `collectionSlug` argument resolves to the intended tree collection before calling getAncestors.","If the collection is genuinely flat, remove the getAncestors call from that code path or branch on whether hierarchy is enabled."],"exampleFix":"// before\nconst ancestors = await getAncestors({ collectionSlug: 'pages', req })\n\n// after\nif (payload.collections['pages']?.config?.hierarchy) {\n  const ancestors = await getAncestors({ collectionSlug: 'pages', req })\n}","handlingStrategy":"validation","validationCode":"import type { Payload } from 'payload'\n\nfunction assertHierarchyEnabled(payload: Payload, slug: string): void {\n  const cfg = payload.collections[slug]?.config\n  if (!cfg) throw new Error(`Collection \"${slug}\" not found`)\n  if (!cfg.hierarchy) {\n    throw new Error(`Collection \"${slug}\" has no hierarchy; cannot call getAncestors`)\n  }\n}\n\n// before calling:\nassertHierarchyEnabled(payload, 'pages')\nawait getAncestors({ collectionSlug: 'pages', req })","typeGuard":"function hasHierarchy(\n  cfg: { hierarchy?: unknown } | undefined,\n): cfg is { hierarchy: Record<string, unknown> } {\n  return Boolean(cfg && cfg.hierarchy)\n}\n\nif (hasHierarchy(payload.collections['pages']?.config)) {\n  await getAncestors({ collectionSlug: 'pages', req })\n}","tryCatchPattern":"try {\n  const ancestors = await getAncestors({ collectionSlug, req })\n} catch (err) {\n  if (err instanceof Error && err.message.includes('does not have hierarchy')) {\n    // collection is flat; skip ancestor resolution\n  } else throw err\n}","preventionTips":["Centralize ancestor-walking behind a helper that pre-checks the hierarchy config.","Keep a list of hierarchy-enabled slugs and validate against it before calling getAncestors.","Add a config-build assertion that flags collections used in tree UIs but missing the hierarchy field."],"tags":["hierarchy","configuration","collections"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}