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

  1. Clear component filters and retry.
  2. Update React DevTools to the latest version.
  3. 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

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


AI-assisted analysis of react/react@22e4f993c7 (2026-08-12). Data as JSON: /api/errors/2b4daf303e8b9eb4. Report an issue: GitHub.