payloadcms/payload · error · Error

Collection is not a hierarchy

Error message

Collection is not a hierarchy

What it means

Thrown by handleHierarchy (the List view's hierarchy data loader) when the collection's sanitized config has no `hierarchy` object. This guard prevents the List view from issuing parent/breadcrumb/children queries against a collection that was never configured as a hierarchy. It is the view-layer counterpart of the getHierarchyAncestry guard.

Source

Thrown at packages/ui/src/views/List/handleHierarchy.ts:47

}: {
  baseFilter?: null | Where
  collectionConfig: SanitizedCollectionConfig
  collectionSlug: string
  parentId: null | number | string
  permissions?: SanitizedPermissions
  req: PayloadRequest
  search?: string
  /** Filter hierarchy items by their collectionSpecific type field */
  typeFilter?: string[]
  user: PayloadRequest['user']
}): Promise<HierarchyViewData> => {
  const hierarchyConfig =
    collectionConfig.hierarchy && typeof collectionConfig.hierarchy === 'object'
      ? collectionConfig.hierarchy
      : undefined

  if (!hierarchyConfig) {
    throw new Error('Collection is not a hierarchy')
  }

  const parentFieldName = hierarchyConfig.parentFieldName

  const useAsTitle = collectionConfig.admin?.useAsTitle || 'id'

  // Fetch the parent item and breadcrumbs (skip for root level)
  let parent: null | (Record<string, unknown> & TypeWithID) = null
  let breadcrumbs: Array<{ id: number | string; title: string }> = []

  if (parentId !== null) {
    try {
      const [item, ancestors] = await Promise.all([
        req.payload.findByID({
          id: parentId,
          collection: collectionSlug,
          depth: 0,
          overrideAccess: false,

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Enable `hierarchy` config on the collection (`hierarchy: { parentFieldName, ... }`).
  2. Ensure the List view only enters the hierarchy branch for collections where `config.hierarchy` is an object.
  3. Update routing so non-hierarchy collections never resolve to `viewType: 'hierarchy'`.
  4. If hierarchy was intentionally removed, clear stale `parent` query params that trigger the hierarchy branch.

Example fix

// before: 'folders' has no hierarchy config but is routed to hierarchy view

// after: declare hierarchy on the collection
// export const Folders = {
//   slug: 'folders',
//   hierarchy: { parentFieldName: 'parent' },
//   fields: [{ name: 'parent', type: 'relationship', relationTo: 'folders' }],
// }
Defensive patterns

Strategy: type-guard

Validate before calling

if (
  !collectionConfig.hierarchy ||
  typeof collectionConfig.hierarchy !== 'object'
) {
  // not a hierarchy - do not enter the hierarchy branch of the List view
}

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 in routing:
// const isHierarchyView = viewType === 'hierarchy' && isHierarchyCollection(collectionConfig)
// if (isHierarchyView) { await handleHierarchy(...) }

Prevention

When it happens

Trigger: `viewType === 'hierarchy'` requested for a non-hierarchy collection; the `hierarchy` config removed but the view still routed there; custom routing that forces the hierarchy branch; a parent query param present on a non-hierarchy collection.

Common situations: Disabling hierarchy on a collection without updating the List routing, slug renames that orphan hierarchy routing, custom List overrides entering the hierarchy branch unconditionally.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/607f45b2aa94a151. Report an issue: GitHub.