facebook/react · error · Error
Did not expect a host hoistable to be the root
Error message
Did not expect a host hoistable to be the root
What it means
DevTools backend invariant from the mount traversal: a HostHoistable fiber (React 19 hoistables such as <link rel=stylesheet precedence>, hoisted <style>/<script>/<title>) has no reconciling parent instance, i.e. the hoistable is being processed as the root of the mirrored tree. DevTools expects hoistables to always be attributed to a nearest composite parent, never to be the traversal root.
Source
Thrown at packages/react-devtools-shared/src/backend/fiber/renderer.js:3444
const elementType = getElementTypeForFiber(fiber);
// If an ancestor updated, we should mark the nearest host nodes for highlighting.
if (elementType === ElementTypeHostComponent) {
traceUpdatesForNodes.add(fiber.stateNode);
traceNearestHostComponentUpdate = false;
}
}
// We intentionally do not re-enable the traceNearestHostComponentUpdate flag in this branch,
// because we don't want to highlight every host node inside of a newly mounted subtree.
}
trackDebugInfoFromLazyType(fiber);
trackDebugInfoFromUsedThenables(fiber);
if (fiber.tag === HostHoistable) {
const nearestInstance = reconcilingParent;
if (nearestInstance === null) {
throw new Error('Did not expect a host hoistable to be the root');
}
aquireHostResource(nearestInstance, fiber.memoizedState);
trackDebugInfoFromHostResource(nearestInstance, fiber);
} else if (
fiber.tag === HostComponent ||
fiber.tag === HostText ||
fiber.tag === HostSingleton
) {
const nearestInstance = reconcilingParent;
if (nearestInstance === null) {
throw new Error('Did not expect a host hoistable to be the root');
}
aquireHostInstance(nearestInstance, fiber.stateNode);
trackDebugInfoFromHostComponent(nearestInstance, fiber);
}
if (isSuspendedOffscreen(fiber)) {
// If an Offscreen component is hidden, mount its children as disconnected.View on GitHub (pinned to eafeac097b)
Solutions
- Update React DevTools to a build that supports React 19 hoistables (HostHoistable tag handling)
- Align React and DevTools release channels (canary React needs the matching DevTools build)
- If reproducible, file an issue with the hoistable markup that triggers it (link/style/script with precedence)
- As a temporary workaround, move the hoistable out of the traversed root position or use plain host elements
Defensive patterns
Strategy: try-catch
Try / catch
try {
backend.handleCommitFiberRoot(renderer, root);
} catch (e) {
if (/Did not expect a host hoistable to be the root/.test(e.message)) {
reportDevToolsBug(e, {hoistables: collectHoistables(root)});
} else throw e;
} Prevention
- Use a DevTools build that supports React 19 hoistables when rendering <link precedence>/<style>/<title> near the root
- Keep hoistable elements stable across renders (stable href/precedence) so they are not reprocessed as traversal roots
- Align React and DevTools release channels before testing hoisting features
- Report hoistable markup that reliably triggers the error
When it happens
Trigger: A hoistable fiber appearing at the point where mountChildrenRecursively starts (root-level fiber), typically when DevTools begins mirroring at a fiber that is itself a hoistable; renderer/DevTools version skew around React 19 resource hoisting.
Common situations: React 19 documents using hoistable tags (<link precedence>, <title>, <meta>) rendered near the root while using an older DevTools backend that lacks support for the hoistable attribution model.
Related errors
- The should not be any remaining suspense node children if th
- There should always be an Offscreen Fiber child in a hydrate
- A dehydrated Suspense node should not have a content Fiber.
- Encountered a dehydrated Suspense boundary that was previous
- The children should not have changed if we pass in the same
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/ba5b8aee2b6efe35.
Report an issue: GitHub.