payloadcms/payload · error · Error
Collection "${hierarchySlug}" is not a hierarchy
Error message
Collection "${hierarchySlug}" is not a hierarchy What it means
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.
Source
Thrown at packages/ui/src/utilities/getHierarchyAncestry.ts:41
*/
export async function getHierarchyAncestry({
hierarchySlug,
ids,
payload,
user,
}: GetHierarchyAncestryArgs): Promise<HierarchyAncestryResult> {
if (ids.length === 0) {
return { items: [] }
}
const collectionConfig = payload.collections[hierarchySlug]?.config
const hierarchyConfig =
collectionConfig?.hierarchy && typeof collectionConfig.hierarchy === 'object'
? collectionConfig.hierarchy
: undefined
if (!hierarchyConfig) {
throw new Error(`Collection "${hierarchySlug}" is not a hierarchy`)
}
const parentFieldName = hierarchyConfig.parentFieldName
const useAsTitle = collectionConfig.admin?.useAsTitle || 'id'
// Cache for already-fetched items to avoid redundant queries
const itemCache = new Map<number | string, Record<string, unknown>>()
const fetchItem = async (id: number | string): Promise<null | Record<string, unknown>> => {
const cached = itemCache.get(id)
if (cached) {
return cached
}
try {
const item = await payload.findByID({
id,
collection: hierarchySlug,View on GitHub (pinned to 00c58b35c0)
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.
Example fix
// before: 'tags' has no hierarchy config
getHierarchyAncestry({ hierarchySlug: 'tags', ids, payload })
// after: declare hierarchy on the collection
// export const Tags = {
// slug: 'tags',
// hierarchy: { parentFieldName: 'parent' },
// fields: [{ name: 'parent', type: 'relationship', relationTo: 'tags' }],
// } Defensive patterns
Strategy: type-guard
Validate before calling
const cfg = payload.collections[hierarchySlug]?.config
if (!cfg?.hierarchy || typeof cfg.hierarchy !== 'object') {
// 'hierarchySlug' is not a hierarchy - skip the ancestry call
} Type guard
function isHierarchyCollection(
cfg: unknown,
): cfg is { hierarchy: Record<string, unknown> } {
return (
!!cfg &&
typeof cfg === 'object' &&
'hierarchy' in cfg &&
typeof (cfg as { hierarchy: unknown }).hierarchy === 'object' &&
(cfg as { hierarchy: unknown }).hierarchy !== null
)
}
// usage:
// if (isHierarchyCollection(payload.collections[hierarchySlug]?.config)) {
// await getHierarchyAncestry({ hierarchySlug, ids, payload })
// } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Collection ${collectionSlug} is not a hierarchy
- The hierarchy title field "${titleFieldName}" was not found.
- Collection "${collectionSlug}" not found
- Collection is not a hierarchy
- Invalid template given
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/8be2d492c71718ca.
Report an issue: GitHub.