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
- Update @headlessui/react to a single consistent version across the project
- Deduplicate the package: check npm ls @headlessui/react and add a resolution/override so only one copy exists
- Avoid importing or re-exporting internal modules of @headlessui/react; use the public components which render StableCollection themselves
- 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
- Pin one version of @headlessui/react and dedupe dependencies
- Never import from internal module paths
- Keep provider/component trees identical on server and client for SSR
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
- A <Transition.Child /> is used but it is missing a parent <T
- Passing props on "Fragment"! The current component <${name}
- Missing parent
- [Headless UI]: Cannot find ownerDocument for contextElement:
- A <TransitionChild /> is used but it is missing a parent <Tr
AI-assisted analysis of tailwindlabs/headlessui@eea57cf46f (2026-08-28).
Data as JSON: /api/errors/c62e29d8570f8b6c.
Report an issue: GitHub.