facebook/react · error · Error

558

558

Error message

Client rendering an Activity suspended it again. This is a bug in React.

What it means

updateActivityComponent() drives <Activity> boundaries during hydration. When a hydration attempt fails, React retries the boundary as a client render via retryActivityComponentWithoutHydrating. On a later render pass, arriving at the same boundary with no ForceClientRender flag and no remaining dehydrated state is a state the design treats as impossible, so it throws.

Source

Thrown at packages/react-reconciler/src/ReactFiberBeginWork.js:1137

        renderLanes,
      );
    } else if (
      (workInProgress.memoizedState as null | ActivityState) !== null
    ) {
      // Something suspended and we should still be in dehydrated mode.
      // Leave the existing child in place.

      workInProgress.child = current.child;
      // The dehydrated completion pass expects this flag to be there
      // but the normal offscreen pass doesn't.
      workInProgress.flags |= DidCapture;
      return null;
    } else {
      // We called retryActivityComponentWithoutHydrating and tried client rendering
      // but now we suspended again. We should never arrive here because we should
      // not have pushed a suspense handler during that second pass and it should
      // instead have suspended above.
      throw new Error(
        'Client rendering an Activity suspended it again. This is a bug in React.',
      );
    }
  }
}

function updateActivityComponent(
  current: null | Fiber,
  workInProgress: Fiber,
  renderLanes: Lanes,
) {
  const nextProps: ActivityProps = workInProgress.pendingProps;

  // Check if the first pass suspended.
  const didSuspend = (workInProgress.flags & DidCapture) !== NoFlags;
  workInProgress.flags &= ~DidCapture;

  if (current === null) {

View on GitHub (pinned to eafeac097b)

Solutions

  1. Update to the latest React canary - the Activity hydration state machine has received multiple fixes
  2. Replace the <Activity> with <Suspense> in a repro to confirm the boundary type is required, then file an issue with the SSR + hydration steps
  3. Preload the data used inside the Activity subtree so the client render resolves synchronously and never suspends twice
  4. Verify server and client render the same tree shape around the boundary - conditional tree mismatches prolong the buggy path
Defensive patterns

Strategy: try-catch

Try / catch

Thrown during render, so an ErrorBoundary above the Activity boundary may catch it - but treat the tree as suspect: log the error, fall back to a non-Activity tree shape, and remount if the boundary keeps failing.

Prevention

When it happens

Trigger: Hydrating an <Activity> boundary whose content suspends; the first client-render retry suspends again inside the same boundary instead of bubbling to an outer Suspense handler. Reachable only through internal bugs in the dehydrated-Activity state machine, not through any supported public API.

Common situations: Streaming SSR with nested Activity/Suspense boundaries and client-suspending data; React canary builds after <Activity> shipped; selective hydration combined with Activity mode="hidden".

Related errors


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