facebook/react · error · Error

299

299

Error message

Target container is not a DOM element.

What it means

In the legacy ReactDOM.render path, the container is validated with isValidContainer (Element/Document/DocumentFragment nodeTypes) and throws error 299 when it is null or not a DOM node. In React 19 builds this line is unreachable because the disableLegacyMode throw (code 509) fires first; error 299 on this path indicates a build with legacy mode still enabled (React 18-style) receiving a bad container.

Source

Thrown at packages/react-dom/src/client/ReactDOMRootFB.js:411

  if (disableLegacyMode) {
    if (__DEV__) {
      console.error(
        'ReactDOM.render was removed in React 19. Use createRoot instead.',
      );
    }
    throw new Error('ReactDOM: Unsupported Legacy Mode API.');
  }
  if (__DEV__) {
    console.error(
      'ReactDOM.render has not been supported since React 18. Use createRoot ' +
        'instead. Until you switch to the new API, your app will behave as ' +
        "if it's running React 17. Learn " +
        'more: https://react.dev/link/switch-to-createroot',
    );
  }

  if (!isValidContainer(container)) {
    throw new Error('Target container is not a DOM element.');
  }

  if (__DEV__) {
    const isModernRoot =
      isContainerMarkedAsRoot(container) &&
      container._reactRootContainer === undefined;
    if (isModernRoot) {
      console.error(
        'You are calling ReactDOM.render() on a container that was previously ' +
          'passed to ReactDOMClient.createRoot(). This is not supported. ' +
          'Did you mean to call root.render(element)?',
      );
    }
  }
  return legacyRenderSubtreeIntoContainer(
    null,
    // $FlowFixMe[incompatible-type]
    element,

View on GitHub (pinned to eafeac097b)

Solutions

  1. Null-check the container before calling ReactDOM.render and fix the selector/id
  2. Ensure the script runs after the DOM parses (defer, end of body)
  3. Migrate to createRoot(container).render(...), which reports the same problem with the modern API

Example fix

// before
ReactDOM.render(<App />, document.getElementById('root'));

// after
const el = document.getElementById('root');
if (el) {
  ReactDOM.render(<App />, el);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const el = document.getElementById('root');
const isValid = !!(
  el &&
  typeof el === 'object' &&
  (el.nodeType === 1 || el.nodeType === 9 || el.nodeType === 11)
);
if (isValid) {
  ReactDOM.render(<App />, el);
} else {
  throw new Error('Root container missing — check the mount element before render');
}

Type guard

function isValidLegacyContainer(node: unknown): node is Element | Document | DocumentFragment {
  return !!(
    node &&
    typeof node === 'object' &&
    (node.nodeType === 1 || node.nodeType === 9 || node.nodeType === 11)
  );
}

Prevention

When it happens

Trigger: ReactDOM.render(<App />, container) on a legacy-mode build where container is null (failed getElementById), a selector string, or another non-DOM value.

Common situations: React 18 codebases calling render before the DOM is ready; typo'd root ids; templates missing the mount div while legacy API is still in use.

Related errors


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