facebook/react · error · Error

The `<html>` tag may only be rendered once.

Error message

The `<html>` tag may only be rendered once.

What it means

Thrown by pushStartHtml when a second root-level <html> begins rendering (preamble.htmlChunks already set and insertionMode === ROOT_HTML_MODE). Fizz tracks the single document element in the preamble; a second <html> finds the slot taken and throws, since an HTML document can contain only one root <html> element.

Source

Thrown at packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:3808

    // This <head> is deep and is likely just an error. we emit it inline though.
    // Validation should warn that this tag is the the wrong spot.
    return pushStartGenericElement(target, props, 'body', formatContext);
  }
}

function pushStartHtml(
  target: Array<Chunk | PrecomputedChunk>,
  props: Object,
  renderState: RenderState,
  preambleState: null | PreambleState,
  formatContext: FormatContext,
): ReactNodeList {
  if (formatContext.insertionMode === ROOT_HTML_MODE) {
    // This <html> is the Document.documentElement
    const preamble = preambleState || renderState.preamble;

    if (preamble.htmlChunks) {
      throw new Error(`The ${'`<html>`'} tag may only be rendered once.`);
    }

    // Insert a marker in the body where the contribution to the head was in case we need to clear it.
    if (preambleState !== null) {
      target.push(htmlPreambleContributionChunk);
    }

    preamble.htmlChunks = [DOCTYPE];
    return pushStartSingletonElement(
      preamble.htmlChunks,
      props,
      'html',
      formatContext,
    );
  } else {
    // This <html> is deep and is likely just an error. we emit it inline though.
    // Validation should warn that this tag is the the wrong spot.
    return pushStartGenericElement(target, props, 'html', formatContext);

View on GitHub (pinned to eafeac097b)

Solutions

  1. Render <html> exactly once at the very root of the server tree
  2. Strip <html>/<head>/<body> from any nested page/component and keep only their inner content
  3. If a second full document is truly needed, render it as a separate stream (separate renderToPipeableStream call), not nested

Example fix

// before
// layout: <html>{children}</html>
// page: <html><body><h1/></body></html>

// after: page renders content only
<>
  <h1>Hello</h1>
</>
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Server-rendering two <html> elements at the root — e.g. a root layout with <html> and a child route or imported component that also returns <html>...</html>, or concatenating two full-document templates into one tree.

Common situations: Framework migrations where a page kept its old <html> wrapper; embedding a complete standalone page (error pages, email templates) inside an app tree; testing utilities that render a full document as the root and also wrap it.

Related errors


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