facebook/react · error · Error
299
299
Error message
Target container is not a DOM element.
What it means
The top-level react-dom entry re-exports createPortal with the same isValidContainer validation as the client build (nodeType ELEMENT, DOCUMENT, or DOCUMENT_FRAGMENT), throwing error 299 for null or non-DOM containers. A distinct trap for this entry point: importing createPortal from 'react-dom' in non-DOM environments like React Native fails here because no real DOM nodes exist at all.
Source
Thrown at packages/react-dom/src/shared/ReactDOM.js:63
console.error(
'React depends on Map and Set built-in types. Make sure that you load a ' +
'polyfill in older browsers. https://reactjs.org/link/react-polyfills',
);
}
}
function batchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
// batchedUpdates is now just a passthrough noop
return fn(a);
}
function createPortal(
children: ReactNodeList,
container: Element | DocumentFragment,
key: ?string = null,
): React$Portal {
if (!isValidContainer(container)) {
throw new Error('Target container is not a DOM element.');
}
// TODO: pass ReactDOM portal implementation as third argument
// $FlowFixMe[incompatible-type] The Flow type is opaque but there's no way to actually create it.
return createPortalImpl(children, container, null, key);
}
export {
ReactVersion as version,
browser,
createPortal,
flushSync,
batchedUpdates as unstable_batchedUpdates,
prefetchDNS,
preconnect,
preload,
preloadModule,
preinit,View on GitHub (pinned to eafeac097b)
Solutions
- Null-check the container before creating the portal
- Prefer the createPortal re-export from 'react-dom/client' for web apps
- On React Native, use a modal/portal library built for native instead of react-dom's createPortal
- Ensure the host element is present before the render that creates the portal
Example fix
// before
import {createPortal} from 'react-dom';
createPortal(<Menu />, document.getElementById('menu-host'));
// after
import {createPortal} from 'react-dom/client';
const host = document.getElementById('menu-host');
if (host) {
createPortal(<Menu />, host);
} Defensive patterns
Strategy: type-guard
Validate before calling
const isValidPortalContainer = (node: unknown): boolean =>
!!(
node &&
typeof node === 'object' &&
(node.nodeType === 1 || node.nodeType === 9 || node.nodeType === 11)
);
const host = document.getElementById('menu-host');
if (isValidPortalContainer(host)) {
createPortal(<Menu />, host);
} Type guard
function isValidPortalContainer(node: unknown): node is Element | Document | DocumentFragment {
return !!(
node &&
typeof node === 'object' &&
(node.nodeType === 1 || node.nodeType === 9 || node.nodeType === 11)
);
} Prevention
- Null-check container lookups before creating portals
- Import createPortal from react-dom/client in web apps; keep react-dom's portal export out of shared cross-platform code
- Never call react-dom's createPortal in React Native — use a native modal/portal library
When it happens
Trigger: import {createPortal} from 'react-dom' with a container that is null (failed getElementById), a selector string, a wrapped node, or — in React Native — any host component, since those are not DOM elements.
Common situations: Shared code that renders portals imported by both web and React Native builds; missing portal host divs in templates; containers looked up before they exist.
Related errors
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/0df95418b076074b.
Report an issue: GitHub.