facebook/react · warning

Could not suspend ID '${suspendedSet[i]}' since the instance

Error message

Could not suspend ID '${suspendedSet[i]}' since the instance can't be found.

What it means

overrideSuspenseMilestone() implements the Suspense scrubber: given a suspendedSet of element ids captured at a milestone, it re-suspends each one. When an id from that set is no longer in idToDevToolsInstanceMap it warns 'Could not suspend ID ... since the instance can't be found' and continues with the remaining ids. The set is a point-in-time snapshot, so any boundary that unmounted since the milestone was recorded triggers this; the scrub still applies to everything that survives.

Source

Thrown at packages/react-devtools-shared/src/backend/fiber/renderer.js:7578

   * @param suspendedSet List of IDs of SuspenseComponent Fibers
   */
  function overrideSuspenseMilestone(suspendedSet: Array<FiberInstance['id']>) {
    if (
      typeof setSuspenseHandler !== 'function' ||
      typeof scheduleUpdate !== 'function'
    ) {
      throw new Error(
        'Expected overrideSuspenseMilestone() to not get called for earlier React versions.',
      );
    }

    const unsuspendedSet: Set<Fiber> = new Set(forceFallbackForFibers);

    let resuspended = false;
    for (let i = 0; i < suspendedSet.length; ++i) {
      const instance = idToDevToolsInstanceMap.get(suspendedSet[i]);
      if (instance === undefined) {
        console.warn(
          `Could not suspend ID '${suspendedSet[i]}' since the instance can't be found.`,
        );
        continue;
      }

      if (instance.kind === FIBER_INSTANCE) {
        const fiber = instance.data;
        if (
          forceFallbackForFibers.has(fiber) ||
          (fiber.alternate !== null &&
            forceFallbackForFibers.has(fiber.alternate))
        ) {
          // We're already forcing fallback for this fiber. Mark it as not unsuspended.
          unsuspendedSet.delete(fiber);
          if (fiber.alternate !== null) {
            unsuspendedSet.delete(fiber.alternate);
          }
        } else {

View on GitHub (pinned to eafeac097b)

Solutions

  1. Accept the partial scrub - remaining boundaries still re-suspend; re-record a milestone on the current tree for a full set.
  2. Reload the page and recapture milestones so the suspendedSet matches live ids.
  3. Avoid unmounting/remounting boundaries between recording a milestone and scrubbing to it.
  4. Embedders: filter your suspendedSet against live store ids (store.getElementByID) before invoking the scrub API.

Example fix

// before
bridge.send('overrideSuspenseMilestone', {rendererID, suspendedSet});

// after - drop ids that no longer resolve before scrubbing
const liveSet = suspendedSet.filter(id => store.getElementByID(id) !== null);
bridge.send('overrideSuspenseMilestone', {rendererID, suspendedSet: liveSet});
Defensive patterns

Strategy: validation

Validate before calling

// before scrubbing to a milestone, keep only ids that still resolve
const liveSuspendedSet = suspendedSet.filter(id => store.getElementByID(id) !== null);
bridge.send('overrideSuspenseMilestone', {rendererID, suspendedSet: liveSuspendedSet});

Type guard

function isLiveElement(store: Store, id: number): boolean %checks {
  return store.getElementByID(id) !== null;
}

Prevention

When it happens

Trigger: Scrubbing the Suspense timeline back to a milestone whose boundaries have since unmounted (route change, list mutation); a milestone recorded before an HMR remount; scrubbing after component filters removed a boundary from the tracked tree.

Common situations: Using the Suspense scrubber on apps whose boundaries churn between milestones; live-reload during timeline inspection; automated replay harnesses feeding old milestone snapshots.

Related errors


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