facebook/react · error

327

327

Error message

Should not already be working.

What it means

performWorkOnRoot is the entry point for performing sync work on a root; before touching the tree it asserts the reconciler is idle (executionContext free of RenderContext and CommitContext). Re-entering it while a render or commit is already in progress means work was scheduled re-entrantly from inside render/commit — either a misused synchronous API (flushSync-style flush at an illegal point) or a genuine reconciler bug (error code 327).

Source

Thrown at packages/react-reconciler/src/ReactFiberWorkLoop.js:1143

  const current = root.current;
  current.lanes = lane;
  markRootUpdated(root, lane);
  ensureRootIsScheduled(root);
}

export function isUnsafeClassRenderPhaseUpdate(fiber: Fiber): boolean {
  // Check if this is a render phase update. Only called by class components,
  // which special (deprecated) behavior for UNSAFE_componentWillReceive props.
  return (executionContext & RenderContext) !== NoContext;
}

export function performWorkOnRoot(
  root: FiberRoot,
  lanes: Lanes,
  forceSync: boolean,
): void {
  if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
    throw new Error('Should not already be working.');
  }

  if (enableProfilerTimer && enableComponentPerformanceTrack) {
    if (workInProgressRootRenderLanes !== NoLanes && workInProgress !== null) {
      const yieldedFiber = workInProgress;
      // We've returned from yielding to the event loop. Let's log the time it took.
      const yieldEndTime = now();
      switch (yieldReason) {
        case SuspendedOnImmediate:
        case SuspendedOnData:
          logSuspendedYieldTime(yieldStartTime, yieldEndTime, yieldedFiber);
          break;
        case SuspendedOnAction:
          logActionYieldTime(yieldStartTime, yieldEndTime, yieldedFiber);
          break;
        default:
          logYieldTime(yieldStartTime, yieldEndTime);
      }

View on GitHub (pinned to eafeac097b)

Solutions

  1. Check for duplicate or mismatched react/react-dom copies (npm ls react react-dom) and dedupe them; both must be the same exact version
  2. Audit for flushSync (or renderer sync flush APIs) invoked during render or commit phases and move the call to an event handler or effect
  3. Upgrade react and react-dom together to the latest stable release
  4. If it persists on the latest stable release with one package copy, file a React issue with a minimal reproduction

Example fix

// before
function Row({row}) {
  // render-phase flushSync re-enters the work loop
  if (row.needsFocus) flushSync(() => setFocused(row.id));
  return <div>{row.id}</div>;
}

// after
function Row({row}) {
  useEffect(() => {
    if (row.needsFocus) setFocused(row.id); // scheduled, not re-entrant
  }, [row.id]);
  return <div>{row.id}</div>;
}
Defensive patterns

Strategy: try-catch

Validate before calling

import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
if (React.version !== ReactDOM.version) {
  throw new Error(`react ${React.version} != react-dom ${ReactDOM.version}`);
}

Try / catch

// last-resort boundary so an internal invariant surfaces instead of white-screening silently
class InvariantBoundary extends React.Component {
  state = {error: null};
  static getDerivedStateFromError(error) { return {error}; }
  componentDidCatch(error, info) { reportToTracker({error, info, reactVersion: React.version}); }
  render() { return this.state.error ? <CrashScreen error={this.state.error} /> : this.props.children; }
}

Prevention

When it happens

Trigger: A synchronous update being performed on a root while executionContext already includes RenderContext or CommitContext — e.g. a flushSync-like synchronous flush triggered from within a component render or a commit-phase code path on the legacy sync route.

Common situations: Two copies or mismatched versions of react and react-dom in one page (bundling, aliasing, dedupe failures) each running their own work loop; third-party renderers or devtools hooking the reconciler; canary/experimental regressions; genuine reconciler bugs filed as GitHub issues.

Related errors


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