This error occurs when ReactDOM.createRoot() or ReactDOM.render() is called with a null or invalid container element, typically because the DOM element does not exist when the script runs or the element ID does not match.
This error is thrown by React when you attempt to render your application into a container that either doesn't exist in the DOM or isn't a valid DOM element. When you call ReactDOM.createRoot() or the legacy ReactDOM.render(), React expects the container argument to be a valid HTMLElement. If document.getElementById() or similar DOM queries return null, React cannot mount your component tree and throws this error. The error typically surfaces in one of two scenarios: either your script is executing before the target DOM element has been added to the page, or there's a mismatch between the ID/selector you're using in your code and what actually exists in your HTML file. In modern React applications using create-react-app or similar tools, this often happens when the root element ID is changed in index.html but not in the corresponding JavaScript file.
Open your index.html file and confirm the root element exists with the correct ID:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
</head>
<body>
<div id="root"></div>
<!-- Your script tags -->
</body>
</html>Make sure the id attribute matches exactly what you're using in your JavaScript code.
In your main JavaScript file (usually index.js or main.jsx), verify the ID matches your HTML:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
// Make sure this ID matches your HTML
const rootElement = document.getElementById('root');
if (!rootElement) {
throw new Error('Root element not found');
}
const root = ReactDOM.createRoot(rootElement);
root.render(<App />);Add a null check to get a clearer error message if the element is missing.
Ensure your script tags are placed after the root div element:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
</head>
<body>
<div id="root"></div>
<!-- Script tags AFTER the root div -->
<script src="bundle.js"></script>
</body>
</html>This ensures the DOM element exists before your script tries to access it.
If you must place scripts in the <head>, add the defer attribute:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
<!-- defer ensures script runs after DOM is parsed -->
<script defer src="bundle.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>The defer attribute tells the browser to download the script but wait to execute it until the DOM is fully parsed.
If you need to ensure the DOM is ready, wrap your React initialization:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
document.addEventListener('DOMContentLoaded', () => {
const rootElement = document.getElementById('root');
if (!rootElement) {
console.error('Failed to find root element');
return;
}
const root = ReactDOM.createRoot(rootElement);
root.render(<App />);
});This guarantees the DOM is fully loaded before React tries to mount.
React 18 vs Legacy API: This error can occur with both ReactDOM.createRoot() (React 18+) and the legacy ReactDOM.render(). If you're upgrading from React 17 or earlier, ensure you've updated both the API call and verified your root element.
Build Tool Considerations: When using Vite, create-react-app, or other build tools, the entry point and HTML template may be in different locations. Vite uses index.html at the project root, while create-react-app uses public/index.html. Always check the correct file for your build setup.
Dynamic Element IDs: Avoid changing the root element ID dynamically or using templated IDs unless you have a specific reason. Stick with the conventional root ID for consistency across projects and to match documentation examples.
Server-Side Rendering: In SSR frameworks like Next.js, you typically don't call createRoot() manually. This error in an SSR context usually indicates you're trying to use client-side only React APIs. Use the framework's rendering methods instead.
Multiple React Roots: Modern React supports multiple roots on a single page. Ensure each createRoot() call targets a unique, existing DOM element. Don't try to create multiple roots on the same container.
Prop spreading could cause security issues
Prop spreading could cause security issues
Error: error:0308010C:digital envelope routines::unsupported
Error: error:0308010C:digital envelope routines::unsupported
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.
React Hook useEffect placed inside a condition
Hook can only be called inside the body of a function component
Hook can only be called inside the body of a function component
Rollup failed to resolve import during build
How to fix "Rollup failed to resolve import" in React