facebook/react · error · Error
render: Unsupported Legacy Mode API.
Error message
render: Unsupported Legacy Mode API.
What it means
ReactFabric.render throws immediately when the renderer build was compiled with disableLegacyMode (the legacy root mode removed) and render is invoked without concurrentRoot=true. It is a hard guard that prevents the legacy ReactDOM.render-style entry point from silently creating an unsupported legacy root in builds where legacy mode no longer exists.
Source
Thrown at packages/react-native-renderer/src/ReactFabric.js:116
if (logError === false) {
return;
}
defaultOnCaughtError(error, errorInfo);
}
function nativeOnDefaultTransitionIndicator(): void | (() => void) {
// Native doesn't have a default indicator.
}
function render(
element: Element<ElementType>,
containerTag: number,
callback: ?() => void,
concurrentRoot: ?boolean,
options: ?RenderRootOptions,
): ?ElementRef<ElementType> {
if (disableLegacyMode && !concurrentRoot) {
throw new Error('render: Unsupported Legacy Mode API.');
}
let root = roots.get(containerTag);
if (!root) {
// TODO: these defaults are for backwards compatibility.
// Once RN implements these options internally,
// we can remove the defaults and ReactFiberErrorDialog.
let onUncaughtError = nativeOnUncaughtError;
let onCaughtError = nativeOnCaughtError;
let onRecoverableError = defaultOnRecoverableError;
if (options && options.onUncaughtError !== undefined) {
onUncaughtError = options.onUncaughtError;
}
if (options && options.onCaughtError !== undefined) {
onCaughtError = options.onCaughtError;
}View on GitHub (pinned to eafeac097b)
Solutions
- Switch to the concurrent API: ReactFabric.createRoot(containerTag, options).render(element), or RN's modern AppRegistry registration so concurrentRoot is true.
- Pass concurrentRoot=true at every call site you control.
- If legacy mode is genuinely required, run a react-native-renderer build matching your RN version where disableLegacyMode is off.
Example fix
// before
ReactFabric.render(<App />, containerTag, callback, false);
// after
const root = ReactFabric.createRoot(containerTag, {
onUncaughtError,
onCaughtError,
onRecoverableError,
});
root.render(<App />); Defensive patterns
Strategy: fallback
Try / catch
try {
ReactFabric.render(element, containerTag, callback, false);
} catch (e) {
if (/Unsupported Legacy Mode API/.test(e.message)) {
ReactFabric.createRoot(containerTag).render(element);
} else {
throw e;
}
} Prevention
- Standardize on createRoot / the modern AppRegistry path; never call legacy render().
- Audit libraries and test helpers for direct ReactFabric.render usage.
- Match your react-native-renderer build to your RN version so flags line up.
When it happens
Trigger: Calling ReactFabric.render(element, containerTag, callback, concurrentRoot=null/falsy, options) on a renderer built with disableLegacyMode - typically the legacy AppRegistry/RN bridge render path, direct use of the internal render export, or test helpers still on the legacy API.
Common situations: Newer react-native-renderer builds where the flag is on; old RN apps or libraries pinned to the legacy render API; test setups that call ReactFabric.render directly with no concurrentRoot argument.
Related errors
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/8c2381963e316827.
Report an issue: GitHub.