tailwindlabs/headlessui · error · Error

You must wrap your component in a <StableCollection>

Error message

You must wrap your component in a <StableCollection>

What it means

Headless UI's StableCollection assigns stable indices to sibling items (used e.g. by Tab/Menu keyboard ordering and SSR-consistent ordering). useStableCollectionIndex must run inside a component that is a descendant of <StableCollection>, which provides the context holding the index registry. If the context is absent, the hook throws this error — it is an internal invariant, not something user code normally triggers.

Source

Thrown at packages/@headlessui-react/src/utils/stable-collection.tsx:53

      return [index, release]
    },
  }
}

export function StableCollection({ children }: { children: React.ReactNode | React.ReactNode[] }) {
  let collection = React.useRef(createCollection())

  return (
    <StableCollectionContext.Provider value={collection}>
      {children}
    </StableCollectionContext.Provider>
  )
}

export function useStableCollectionIndex(group: string) {
  let collection = React.useContext(StableCollectionContext)
  if (!collection) throw new Error('You must wrap your component in a <StableCollection>')

  let key = React.useId()
  let [idx, cleanupIdx] = collection.current.get(group, key)
  React.useEffect(() => cleanupIdx, [])
  return idx
}

View on GitHub (pinned to eea57cf46f)

Solutions

  1. Update @headlessui/react to a single consistent version across the project
  2. Deduplicate the package: check npm ls @headlessui/react and add a resolution/override so only one copy exists
  3. Avoid importing or re-exporting internal modules of @headlessui/react; use the public components which render StableCollection themselves
  4. If it appears only on SSR, verify the component tree is identical server/client (no conditional provider based on typeof window)

Example fix

// before (mixing versions)
// v2 <Tab.Group> renders v1 <Tab> internals → context mismatch

// after
npm ls @headlessui/react
// then in package.json:
"overrides": { "@headlessui/react": "^2.2.0" }
Defensive patterns

Strategy: validation

Validate before calling

import pkg from '@headlessui/react/package.json';
// fail fast at startup in dev
if (!pkg.version.startsWith('2.')) console.warn('unexpected @headlessui/react version', pkg.version);

Prevention

When it happens

Trigger: Rendering an internal Headless UI child component that calls useStableCollectionIndex outside its expected <StableCollection> parent; library authors reusing Headless UI internals (importing from @headlessui/react internals) without the provider; version mismatches between @headlessui/react packages or duplicated copies causing two different StableCollectionContext instances; SSR hydration tree differences where the provider renders on one side only.

Common situations: Mixing @headlessui/react v1 and v2 components in one tree (or nested duplicates of the package via npm hoisting bugs); wrapping Headless UI internals in custom builds; monkey-patching or extracting components like Tab/Menu internals.

Related errors


AI-assisted analysis of tailwindlabs/headlessui@eea57cf46f (2026-08-28). Data as JSON: /api/errors/c62e29d8570f8b6c. Report an issue: GitHub.