facebook/react · error · Error

257

257

Error message

Portals are not currently supported by the server renderer. Render them conditionally so that they only appear on the client render.

What it means

Fizz's renderNodeDestructive throws immediately (error code 257) for REACT_PORTAL_TYPE elements: portals need a live DOM target node, which does not exist during server rendering.

Source

Thrown at packages/react-server/src/ReactFizzServer.js:3578

            debugTask.run(
              renderElement.bind(
                null,
                request,
                task,
                keyPath,
                type,
                props,
                ref,
              ),
            );
          } else {
            renderElement(request, task, keyPath, type, props, ref);
          }
        }
        return;
      }
      case REACT_PORTAL_TYPE:
        throw new Error(
          'Portals are not currently supported by the server renderer. ' +
            'Render them conditionally so that they only appear on the client render.',
        );
      case REACT_LAZY_TYPE: {
        const lazyNode: LazyComponentType<any, any> = node as any;
        let resolvedNode;
        if (__DEV__) {
          resolvedNode = callLazyInitInDEV(lazyNode);
        } else {
          const payload = lazyNode._payload;
          const init = lazyNode._init;
          resolvedNode = init(payload);
        }
        if (request.aborted) {
          // eslint-disable-next-line no-throw-literal
          throw null;
        }
        // Now we render the resolved node

View on GitHub (pinned to eafeac097b)

Solutions

  1. Mount portals only on the client: render them after mount (useEffect plus a mounted flag) or behind a typeof document check
  2. Return null for the overlay during SSR and let the client hydrate/mount it
  3. Mark the portal-hosting component 'use client' and mount it after hydration

Example fix

// before
function Modal({children}) {
  return ReactDOM.createPortal(children, document.body); // throws during SSR
}

// after
function Modal({children}) {
  const [mounted, setMounted] = useState(false);
  useEffect(() => setMounted(true), []);
  if (!mounted) return null; // no portal on the server
  return ReactDOM.createPortal(children, document.body);
}
Defensive patterns

Strategy: fallback

Validate before calling

const canUseDOM = typeof document !== 'undefined';
// render portal subtrees only when canUseDOM is true
return canUseDOM ? ReactDOM.createPortal(children, document.body) : null;

Prevention

When it happens

Trigger: Rendering the return value of ReactDOM.createPortal(...) during SSR; a shared modal/tooltip/menu component that unconditionally mounts a portal in its render output.

Common situations: Design-system overlays used inside server-rendered trees; components run through renderToString/renderToStaticMarkup in tests; forgetting that SSR has no document object.

Related errors


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