{"record":{"id":"6c0b6152a55338ee","repo":"facebook/react","slug":"expected-root-pseudo-key-to-be-known","errorCode":null,"errorMessage":"Expected root pseudo key to be known.","messagePattern":"Expected root pseudo key to be known\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-devtools-shared/src/backend/fiber/renderer.js","lineNumber":7792,"sourceCode":"  // Roots don't have a real persistent identity.\n  // A root's \"pseudo key\" is \"childDisplayName:indexWithThatName\".\n  // For example, \"App:0\" or, in case of similar roots, \"Story:0\", \"Story:1\", etc.\n  // We will use this to try to disambiguate roots when restoring selection between reloads.\n  const rootPseudoKeys: Map<number, string> = new Map();\n  const rootDisplayNameCounter: Map<string, number> = new Map();\n\n  function setRootPseudoKey(id: number, fiber: Fiber) {\n    const name = getDisplayNameForRoot(fiber);\n    const counter = rootDisplayNameCounter.get(name) || 0;\n    rootDisplayNameCounter.set(name, counter + 1);\n    const pseudoKey = `${name}:${counter}`;\n    rootPseudoKeys.set(id, pseudoKey);\n  }\n\n  function removeRootPseudoKey(id: number) {\n    const pseudoKey = rootPseudoKeys.get(id);\n    if (pseudoKey === undefined) {\n      throw new Error('Expected root pseudo key to be known.');\n    }\n    const name = pseudoKey.slice(0, pseudoKey.lastIndexOf(':'));\n    const counter = rootDisplayNameCounter.get(name);\n    if (counter === undefined) {\n      throw new Error('Expected counter to be known.');\n    }\n    if (counter > 1) {\n      rootDisplayNameCounter.set(name, counter - 1);\n    } else {\n      rootDisplayNameCounter.delete(name);\n    }\n    rootPseudoKeys.delete(id);\n  }\n\n  function getDisplayNameForRoot(fiber: Fiber): string {\n    let preferredDisplayName = null;\n    let fallbackDisplayName = null;\n    let child = fiber.child;","sourceCodeStart":7774,"sourceCodeEnd":7810,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-devtools-shared/src/backend/fiber/renderer.js#L7774-L7810","documentation":"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.","triggerScenarios":"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.","commonSituations":"Toggling 'hide components' filters while roots concurrently unmount; HMR swapping root components; DevTools attached mid-session to an app already tearing roots down.","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."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// when embedding devtools-shared: root key bookkeeping diverged - rebuild it\ntry {\n  renderer.handleCommitFiberRoot(root, priorityLevel);\n} catch (err) {\n  if (err.message.includes('Expected root pseudo key to be known')) {\n    renderer.setTraceUpdateEnabled?.(false);\n    location.reload(); // only a fresh session reliably rebuilds rootPseudoKeys\n  } else {\n    throw err;\n  }\n}","preventionTips":["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."],"tags":["react-devtools","fiber-root","internal-invariant","bookkeeping"],"backgroundTag":"devtools-internal-invariant","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}