facebook/react · error · Error

Expected overrideSuspenseMilestone() to not get called for e

Error message

Expected overrideSuspenseMilestone() to not get called for earlier React versions.

What it means

overrideSuspenseMilestone(suspendedSet) is the bulk variant used to force a whole set of Suspense boundaries to a milestone state (suspend all listed, resume the rest). Like the single-boundary override it requires setSuspenseHandler and scheduleUpdate from the renderer; on React versions that predate those DevTools hooks it throws, because there is no API to install the bulk handler.

Source

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

    if (!forceFallback && typeof scheduleRetry === 'function') {
      // If we're unsuspending and the renderer supports it, use a Retry instead of Sync
      // to allow for things like View Transitions to proceed the way they would for real.
      scheduleRetry(fiber);
    } else {
      scheduleUpdate(fiber);
    }
  }

  /**
   * Resets the all other roots of this renderer.
   * @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;

View on GitHub (pinned to eafeac097b)

Solutions

  1. Upgrade the page's React to a version that injects setSuspenseHandler and scheduleUpdate.
  2. Before sending the milestone action, verify supportsTogglingSuspense/canToggleSuspense for the renderer and every id in the set.
  3. Reload the page to re-run capability detection after renderer changes.
  4. If you maintain a custom frontend, disable milestone controls when the capability check fails instead of sending the message.
Defensive patterns

Strategy: validation

Validate before calling

// before a bulk/milestone suspend, verify the renderer capability once
const renderer = hook.renderers.get(rendererID);
const canMilestone =
  typeof renderer?.setSuspenseHandler === 'function' &&
  typeof renderer?.scheduleUpdate === 'function';
if (canMilestone) {
  bridge.send('overrideSuspenseMilestone', {ids, rendererID});
}

Prevention

When it happens

Trigger: A bulk suspend/unsuspend action (milestone navigation in the profiler/components UI, or a custom frontend sending the corresponding bridge message with an ID array) while the attached renderer is older than the version that introduced setSuspenseHandler/scheduleUpdate.

Common situations: Newer DevTools frontend driving an older pinned React renderer; embedding devtools-shared and wiring milestone controls without capability checks; renderers swapped by HMR.

Related errors


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