react/react · error · Error
Can't unmount a filtered SuspenseNode. This is a bug.
Error message
Can't unmount a filtered SuspenseNode. This is a bug.
What it means
Thrown in recordSuspenseUnmount when the SuspenseNode's instance kind is not FIBER_INSTANCE (i.e. it is FILTERED_FIBER_INSTANCE or another variant). The unmount path for suspense nodes expects a real, unfiltered FiberInstance because it needs the numeric ID to queue for the removal operation batch. A filtered instance should have been handled differently (or not have a suspense node being unmounted at all).
Source
Thrown at packages/react-devtools-shared/src/backend/fiber/renderer.js:2154
suspenseNode.environments.forEach((count, env) => {
getStringID(env);
});
pendingSuspenderChanges.add(fiberInstance.id);
}
function recordSuspenseUnmount(suspenseInstance: SuspenseNode): void {
// $FlowFixMe[constant-condition]
if (__DEBUG__) {
console.log(
'recordSuspenseUnmount()',
suspenseInstance,
reconcilingParentSuspenseNode,
);
}
const devtoolsInstance = suspenseInstance.instance;
if (devtoolsInstance.kind !== FIBER_INSTANCE) {
throw new Error("Can't unmount a filtered SuspenseNode. This is a bug.");
}
const fiberInstance = devtoolsInstance;
const id = fiberInstance.id;
// To maintain child-first ordering,
// we'll push it into one of these queues,
// and later arrange them in the correct order.
pendingRealUnmountedSuspenseIDs.push(id);
pendingSuspenderChanges.delete(id);
idToSuspenseNodeMap.delete(id);
}
// Running state of the remaining children from the previous version of this parent that
// we haven't yet added back. This should be reset anytime we change parent.
// Any remaining ones at the end will be deleted.
let remainingReconcilingChildren: null | DevToolsInstance = null;
// The previously placed child.View on GitHub (pinned to 22e4f993c7)
Solutions
- Clear component filters and retry.
- Update React DevTools to the latest version.
- If developing DevTools, check that the unmount dispatch routes filtered suspense nodes through the correct (non-throwing) path.
Defensive patterns
Strategy: validation
Validate before calling
// Before calling recordSuspenseUnmount, verify instance kind
if (suspenseInstance.instance.kind === FIBER_INSTANCE) {
recordSuspenseUnmount(suspenseInstance);
} Type guard
function isUnmountableSuspenseNode(node: SuspenseNode): boolean {
return node.instance.kind === FIBER_INSTANCE;
} Prevention
- Avoid changing component filters during Suspense boundary teardown.
- When developing DevTools, route filtered suspense nodes through a non-throwing unmount path.
- Keep DevTools updated to benefit from filter/unmount interaction fixes.
When it happens
Trigger: recordSuspenseUnmount receives a SuspenseNode whose .instance.kind !== FIBER_INSTANCE. This happens when the unmount traversal encounters a suspense node that was created for a filtered fiber but is being processed through the real-unmount queue.
Common situations: Active component filters during Suspense boundary teardown; fast-refresh re-mounting of filtered Suspense components; DevTools version mismatch affecting instance-kind bookkeeping.
Related errors
- Cannot record a mount for a filtered Fiber instance.
- Should not have a filtered instance at this point. This is a
- Did not find a suitable instance for this async info. This i
- Could not send suspender changes for "${fiberIdWithChanges}"
- It should not be possible to have suspended data outside the
AI-assisted analysis of react/react@22e4f993c7 (2026-08-12).
Data as JSON: /api/errors/2b4daf303e8b9eb4.
Report an issue: GitHub.