facebook/react · error · Error

Encountered a dehydrated Suspense boundary that was previous

Error message

Encountered a dehydrated Suspense boundary that was previously hydrated.

What it means

One-way hydration invariant on the update path: the backend asserts a Suspense boundary never goes from hydrated back to dehydrated between two observed fibers. React treats dehydration as terminal per boundary instance, so this transition implies the backend compared mismatched fiber instances or observed commits out of order - i.e. corrupted mirror state or a version-skew bug.

Source

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

              'There should always be an Offscreen Fiber child in a hydrated Suspense boundary.',
            );
          }

          trackThrownPromisesFromRetryCache(suspenseNode, nextFiber.stateNode);
          // Toggle suspended state.
          recordSuspenseSuspenders(suspenseNode);

          mountSuspenseChildrenRecursively(
            nextContentFiber,
            traceNearestHostComponentUpdate,
            stashedSuspenseParent,
            stashedSuspensePrevious,
            stashedSuspenseRemaining,
          );
          // mountSuspenseChildrenRecursively popped already
          shouldPopSuspenseNode = false;
        } else if (previousHydrated && !nextHydrated) {
          throw new Error(
            'Encountered a dehydrated Suspense boundary that was previously hydrated.',
          );
        } else {
          // This Suspense Fiber is still dehydrated. It won't have any children
          // until hydration.
        }
      } else {
        // Common case: Primary -> Primary.
        // This is the same code path as for non-Suspense fibers.
        if (nextFiber.child !== prevFiber.child) {
          updateFlags |= updateChildrenRecursively(
            nextFiber.child,
            prevFiber.child,
            traceNearestHostComponentUpdate,
          );
        } else {
          // Children are unchanged.
          if (fiberInstance !== null) {

View on GitHub (pinned to eafeac097b)

Solutions

  1. Reload the inspected app to reset the DevTools backend mirror completely
  2. Update React DevTools and React to matching versions/channels
  3. Verify the app does not load two React copies (npm ls react)
  4. Report with the DevTools console output and steps if it recurs on clean matching versions
Defensive patterns

Strategy: try-catch

Try / catch

try {
  backend.handleCommitFiberRoot(renderer, root);
} catch (e) {
  if (/dehydrated Suspense boundary that was previously hydrated/.test(e.message)) {
    fullMirrorRebuild(root); // pairing corrupted; rebuild from scratch
  } else throw e;
}

Prevention

When it happens

Trigger: The prev fiber reports hydrated and the next fiber of the 'same' boundary reports dehydrated; typically after earlier swallowed errors desynchronized fiberInstance/fiber pairing, or renderer behavior changes (Activity remounting boundaries) the backend does not model.

Common situations: Long DevTools sessions after a prior invariant failure; canary React changing Suspense remount semantics; duplicated React copies producing alternate fiber identities.

Related errors


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