facebook/react · warning

Detected a large number of updates inside startTransition. I

Error message

Detected a large number of updates inside startTransition. If this is due to a subscription please re-write it to use React provided hooks. Otherwise concurrent mode guarantees are off the table.

What it means

This is the shared warnAboutTransitionSubscriptions helper (ReactStartTransition.js:197), called in the finally block of React.startTransition. Each top-level startTransition scope gets a dev-only _updatedFibers set; fibers scheduling updates while ReactSharedInternals.T points at that transition are added by the work loop. If the scope ends with more than 10 distinct fibers updated, React warns that a subscription is likely inside the scope - updates React did not plan cannot be kept interruptible.

Source

Thrown at packages/react/src/ReactStartTransition.js:197

    }
  } catch (error) {
    reportGlobalError(error);
  } finally {
    ReactSharedInternals.T = prevTransition;
  }
  return noop;
}

function warnAboutTransitionSubscriptions(
  prevTransition: Transition | null,
  currentTransition: Transition,
) {
  if (__DEV__) {
    if (prevTransition === null && currentTransition._updatedFibers) {
      const updatedFibersCount = currentTransition._updatedFibers.size;
      currentTransition._updatedFibers.clear();
      if (updatedFibersCount > 10) {
        console.warn(
          'Detected a large number of updates inside startTransition. ' +
            'If this is due to a subscription please re-write it to use React provided hooks. ' +
            'Otherwise concurrent mode guarantees are off the table.',
        );
      }
    }
  }
}

View on GitHub (pinned to eafeac097b)

Solutions

  1. Replace manual store subscriptions with useSyncExternalStore so scheduling belongs to React
  2. Restructure to a single state update (one parent state object or reducer dispatch) per transition scope
  3. Fire subscription notifications outside the transition, keeping only the intentional state change inside
  4. Accept the dev-only warning if the fan-out is deliberate and you do not rely on interruption for that update

Example fix

// before
startTransition(() => {
  store.notify(); // each listener setStates -> >10 fibers
});

// after
startTransition(() => {
  setSelected(computeSelection(ids)); // one update
});
// listeners read via useSyncExternalStore(store.subscribe, store.getSnapshot)
Defensive patterns

Strategy: validation

Validate before calling

// dev wrapper: assert scope size before entering startTransition
function guardedStartTransition(scope) {
  if (__DEV__ && scope.length > 0) {
    console.warn('startTransition ignores arguments - a subscription may be involved');
  }
  startTransition(scope);
}

Prevention

When it happens

Trigger: import {startTransition} from 'react' and a scope that synchronously updates more than 10 components: startTransition(() => { selectedIds.forEach(id => setters[id](...)); }), or a store.emit()/notify() invoked inside the scope whose subscribers each setState.

Common situations: Multi-select UIs updating per-row state inside one transition; wrapping store commit functions in startTransition; transitions that trigger analytics listeners which themselves setState.

Related errors


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