facebook/react · error · Error

532

532

Error message

Attempted to render a Client Component from renderToHTML. This is not supported since it will never hydrate. Only render Server Components with renderToHTML.

What it means

This fork (ReactFlightServerConfig.markup) implements renderToHTML — static markup generation with no client runtime and no hydration. Client references are meaningless there, so every manifest hook (getClientReferenceKey, resolveClientReferenceMetadata, ...) throws by design. The error fires as soon as the rendered tree contains anything marked 'use client', protecting developers from silently shipping dead interactivity.

Source

Thrown at packages/react-server/src/forks/ReactFlightServerConfig.markup.js:69

export opaque type ClientReferenceMetadata: any = null;
export opaque type ServerReferenceId: string = string;
export opaque type ClientReferenceKey: any = string;

const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
const SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');

export function isClientReference(reference: Object): boolean {
  return reference.$$typeof === CLIENT_REFERENCE_TAG;
}

export function isServerReference(reference: Object): boolean {
  return reference.$$typeof === SERVER_REFERENCE_TAG;
}

export function getClientReferenceKey(
  reference: ClientReference<any>,
): ClientReferenceKey {
  throw new Error(
    'Attempted to render a Client Component from renderToHTML. ' +
      'This is not supported since it will never hydrate. ' +
      'Only render Server Components with renderToHTML.',
  );
}

export function resolveClientReferenceMetadata<T>(
  config: ClientManifest,
  clientReference: ClientReference<T>,
): ClientReferenceMetadata {
  throw new Error(
    'Attempted to render a Client Component from renderToHTML. ' +
      'This is not supported since it will never hydrate. ' +
      'Only render Server Components with renderToHTML.',
  );
}

export function getServerReferenceId<T>(

View on GitHub (pinned to eafeac097b)

Solutions

  1. Switch to the standard render/prerender API with a client manifest so client components are emitted as references.
  2. Remove 'use client' from components used in the static-only tree.
  3. Split static pages from interactive routes and render each with the appropriate API.

Example fix

// before
const html = await renderToHTML(<InteractiveWidget />, options);

// after
const {stream} = render(<InteractiveWidget />, clientManifest);
Defensive patterns

Strategy: type-guard

Validate before calling

const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
export function containsClientReference(node: any, seen = new Set()): boolean {
  if (node == null || typeof node !== 'object' || seen.has(node)) return false;
  seen.add(node);
  if (node.$$typeof === CLIENT_REFERENCE_TAG || node.type?.$$typeof === CLIENT_REFERENCE_TAG) return true;
  return Object.values(node).some(v => containsClientReference(v, seen));
}
// before static rendering:
if (containsClientReference(tree)) throw new Error('tree contains client components — use render/prerender instead');

Type guard

export function isClientReference(v: unknown): boolean {
  return typeof v === 'object' && v !== null && (v as any).$$typeof === Symbol.for('react.client.reference');
}

Prevention

When it happens

Trigger: Calling renderToHTML on a tree containing a component whose file starts with 'use client'; using the markup fork for static site generation while importing interactive components; reusing an app tree built for the standard Flight stream in a markup-only pipeline.

Common situations: Static pre-render pipelines (marketing pages, emails) reusing trees that also contain interactive widgets; migrating from render/prerender to a markup-only fork without splitting the tree.

Related errors


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