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

  1. Update React DevTools to a build that supports React 19 hoistables (HostHoistable tag handling)
  2. Align React and DevTools release channels (canary React needs the matching DevTools build)
  3. If reproducible, file an issue with the hoistable markup that triggers it (link/style/script with precedence)
  4. 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

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


AI-assisted analysis of facebook/react@eafeac097b (2026-08-21). Data as JSON: /api/errors/ba5b8aee2b6efe35. Report an issue: GitHub.