facebook/react · error · Error
Expected root pseudo key to be known.
Error message
Expected root pseudo key to be known.
What it means
Root pseudo keys ('DisplayName:counter') give every root a stable identity used in selection paths. Roots are keyed by setRootPseudoKey during the initial flush, filter re-mounts, and commits; removeRootPseudoKey runs when the backend tears a root down and throws if the id was never keyed. The throw means the backend is unmounting a root whose bookkeeping entry is missing - registration and teardown got out of sync.
Source
Thrown at packages/react-devtools-shared/src/backend/fiber/renderer.js:7792
// Roots don't have a real persistent identity.
// A root's "pseudo key" is "childDisplayName:indexWithThatName".
// For example, "App:0" or, in case of similar roots, "Story:0", "Story:1", etc.
// We will use this to try to disambiguate roots when restoring selection between reloads.
const rootPseudoKeys: Map<number, string> = new Map();
const rootDisplayNameCounter: Map<string, number> = new Map();
function setRootPseudoKey(id: number, fiber: Fiber) {
const name = getDisplayNameForRoot(fiber);
const counter = rootDisplayNameCounter.get(name) || 0;
rootDisplayNameCounter.set(name, counter + 1);
const pseudoKey = `${name}:${counter}`;
rootPseudoKeys.set(id, pseudoKey);
}
function removeRootPseudoKey(id: number) {
const pseudoKey = rootPseudoKeys.get(id);
if (pseudoKey === undefined) {
throw new Error('Expected root pseudo key to be known.');
}
const name = pseudoKey.slice(0, pseudoKey.lastIndexOf(':'));
const counter = rootDisplayNameCounter.get(name);
if (counter === undefined) {
throw new Error('Expected counter to be known.');
}
if (counter > 1) {
rootDisplayNameCounter.set(name, counter - 1);
} else {
rootDisplayNameCounter.delete(name);
}
rootPseudoKeys.delete(id);
}
function getDisplayNameForRoot(fiber: Fiber): string {
let preferredDisplayName = null;
let fallbackDisplayName = null;
let child = fiber.child;View on GitHub (pinned to eafeac097b)
Solutions
- Reload the page with DevTools open to rebuild root bookkeeping from scratch.
- Avoid changing filters at the same moment roots are being created/unmounted.
- Update React DevTools - root-key bookkeeping bugs get fixed in the shared package.
- File a React issue if it reproduces deterministically on current versions.
Defensive patterns
Strategy: fallback
Try / catch
// when embedding devtools-shared: root key bookkeeping diverged - rebuild it
try {
renderer.handleCommitFiberRoot(root, priorityLevel);
} catch (err) {
if (err.message.includes('Expected root pseudo key to be known')) {
renderer.setTraceUpdateEnabled?.(false);
location.reload(); // only a fresh session reliably rebuilds rootPseudoKeys
} else {
throw err;
}
} Prevention
- Do not toggle component filters while roots are concurrently mounting/unmounting.
- Reload with DevTools open after major tree changes instead of relying on long sessions.
- Keep DevTools current for root-key bookkeeping fixes.
When it happens
Trigger: A root is unmounted while its pseudo key was never registered: roots created before DevTools attached or during a filter re-mount window (when keys are rewritten), rapid create/unmount cycles under fast refresh, or double-processing of a root unmount.
Common situations: Toggling 'hide components' filters while roots concurrently unmount; HMR swapping root components; DevTools attached mid-session to an app already tearing roots down.
Related errors
- Expected counter to be known.
- Expected mounted root to have known pseudo key.
- Expected the root instance to exist when computing a path
- Expected a root instance to exist for this Fiber root
- Expected the root instance to already exist when starting pr
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/6c0b6152a55338ee.
Report an issue: GitHub.