facebook/react · error · Error

349

349

Error message

Expected a work-in-progress root. This is a bug in React. Please file an issue.

What it means

Internal invariant inside updateReducer's queue processing. When a hook update carries the GestureLane (optimistic state scheduled by the experimental startGestureTransition API) and the current render is itself a gesture render, React looks up the work-in-progress FiberRoot to compare root.pendingGestures with the update's ScheduledGesture. If getWorkInProgressRoot() returns null at that point the reconciler's state is inconsistent; the message explicitly says this is a bug in React, not in application code.

Source

Thrown at packages/react-reconciler/src/ReactFiberHooks.js:1409

        ? !isSubsetOfLanes(getWorkInProgressRootRenderLanes(), updateLane)
        : !isSubsetOfLanes(renderLanes, updateLane);

      if (enableGestureTransition && updateLane === GestureLane) {
        // This is a gesture optimistic update. It should only be considered as part of the
        // rendered state while rendering the gesture lane and if the rendering the associated
        // ScheduledGesture.
        const scheduledGesture = update.gesture;
        if (scheduledGesture !== null) {
          if (scheduledGesture.count === 0 && !scheduledGesture.committing) {
            // This gesture has already been cancelled. We can clean up this update.
            update = update.next;
            continue;
          } else if (!isGestureRender(renderLanes)) {
            shouldSkipUpdate = true;
          } else {
            const root: FiberRoot | null = getWorkInProgressRoot();
            if (root === null) {
              throw new Error(
                'Expected a work-in-progress root. This is a bug in React. Please file an issue.',
              );
            }
            // We assume that the currently rendering gesture is the one first in the queue.
            shouldSkipUpdate = root.pendingGestures !== scheduledGesture;
          }
        }
      }

      if (shouldSkipUpdate) {
        // Priority is insufficient. Skip this update. If this is the first
        // skipped update, the previous update/state is the new base
        // update/state.
        const clone: Update<S, A> = {
          lane: updateLane,
          revertLane: update.revertLane,
          gesture: update.gesture,
          action: update.action,

View on GitHub (pinned to eafeac097b)

Solutions

  1. File an issue at https://github.com/facebook/react/issues with a minimal repro using startGestureTransition (the message requests it)
  2. Pin the last canary/experimental version that worked, then retest on a newer release where the bug may be fixed
  3. As a workaround, replace startGestureTransition with startTransition or an action (drops the gesture code path entirely)
  4. Verify react and react-dom resolve to the exact same version (no duplicated or mismatched copies)
Defensive patterns

Strategy: try-catch

Try / catch

class GestureErrorBoundary extends React.Component {
  state = {error: null};
  static getDerivedStateFromError(error) {
    return {error};
  }
  componentDidCatch(error) {
    reportToIssueTracker(error); // include React version + startGestureTransition repro
  }
  render() {
    return this.state.error ? <StaticFallback /> : this.props.children;
  }
}

Prevention

When it happens

Trigger: React is replaying a reducer queue that contains a gesture optimistic update (update.lane === GestureLane with a non-null update.gesture), isGestureRender(renderLanes) is true, and getWorkInProgressRoot() returns null while deciding whether to skip the update. Only reachable on builds where the enableGestureTransition flag is on and startGestureTransition was used.

Common situations: Using canary/experimental React builds or this rust-research branch with unstable_startGestureTransition; mixing gesture transitions with hydration, offscreen/Activity trees, or interrupted renders; skew between react and react-dom versions. Apps that never call startGestureTransition cannot hit this path.

Related errors


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