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
- Null-check the container before calling ReactDOM.render and fix the selector/id
- Ensure the script runs after the DOM parses (defer, end of body)
- 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
- Null-check getElementById before every legacy render call
- Verify the script runs after DOM parsing (defer or end of body)
- Migrate to createRoot, which surfaces the same problem with the supported API
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.