facebook/react · error · Error
Expected overrideError() to not get called for earlier React
Error message
Expected overrideError() to not get called for earlier React versions.
What it means
React 16.9+ exposes setErrorHandler/scheduleUpdate through injectIntoDevTools so DevTools can force components to error. shouldErrorFiberAccordingToMap is the handler the backend installs; the guard throws if that handler is ever invoked while setErrorHandler was never a function - i.e. the attached React is too old to support toggling errors, so the backend cannot have promised React this behavior.
Source
Thrown at packages/react-devtools-shared/src/backend/fiber/renderer.js:7412
}
return inst.data.return;
} else {
return devtoolsInstance.data;
}
}
// React will switch between these implementations depending on whether
// we have any manually suspended/errored-out Fibers or not.
function shouldErrorFiberAlwaysNull() {
return null;
}
// Map of Fiber and its force error status: true (error), false (toggled off)
const forceErrorForFibers = new Map<Fiber, boolean>();
function shouldErrorFiberAccordingToMap(fiber: any): boolean | null {
if (typeof setErrorHandler !== 'function') {
throw new Error(
'Expected overrideError() to not get called for earlier React versions.',
);
}
let status = forceErrorForFibers.get(fiber);
if (status === false) {
// TRICKY overrideError adds entries to this Map,
// so ideally it would be the method that clears them too,
// but that would break the functionality of the feature,
// since DevTools needs to tell React to act differently than it normally would
// (don't just re-render the failed boundary, but reset its errored state too).
// So we can only clear it after telling React to reset the state.
// Technically this is premature and we should schedule it for later,
// since the render could always fail without committing the updated error boundary,
// but since this is a DEV-only feature, the simplicity is worth the trade off.
forceErrorForFibers.delete(fiber);
if (forceErrorForFibers.size === 0) {
// Last override is gone. Switch React back to fast path.View on GitHub (pinned to eafeac097b)
Solutions
- Upgrade the page's React to >=16.9 so setErrorHandler and scheduleUpdate exist in the injected renderer.
- Hard-reload the page after changing React versions so DevTools re-attaches to the actual renderer.
- In custom frontends, gate the error-toggle UI on the capability (supportsTogglingError is computed at renderer.js:449-451) and on inspectedElement.canToggleError (renderer.js:6307) instead of calling overrideError unconditionally.
- Check for duplicate React copies (window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers) and remove the stale one.
Example fix
// before (custom DevTools integration)
bridge.send('overrideError', {id, forceError: true, rendererID});
// after - only when the renderer supports it
const renderer = hook.renderers.get(rendererID);
if (typeof renderer?.setErrorHandler === 'function' && typeof renderer?.scheduleUpdate === 'function') {
bridge.send('overrideError', {id, forceError: true, rendererID});
} Defensive patterns
Strategy: validation
Validate before calling
// enable error-override UI only when the renderer supports it (mirrors renderer.js:449-451) const renderer = hook.renderers.get(rendererID); const supportsTogglingError = typeof renderer?.setErrorHandler === 'function' && typeof renderer?.scheduleUpdate === 'function';
Prevention
- Require React >=16.9 in apps that use the error-toggle feature.
- Hard-reload after HMR-swapping react/react-dom versions so capability detection re-runs.
- Check window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers for duplicate/stale React copies.
When it happens
Trigger: The error-override flow runs against a renderer older than 16.9: leftover forceErrorForFibers state from a session where a newer React was attached, or a custom frontend calling the overrideError bridge path while the page's renderer lacks setErrorHandler (e.g. after HMR swapped in an older React bundle without a reload).
Common situations: Legacy codebases pinned to React <16.9 (or 15) with a modern DevTools frontend; two copies of React on the page where DevTools bound the older one; downgrading react/react-dom via hot module replacement.
Related errors
- Expected overrideSuspense() to not get called for earlier Re
- Expected overrideSuspenseMilestone() to not get called for e
- Invalid internal instance: ${internalInstance}
- Expected to find root ID.
- Invalid component filter type "${componentFilter.type}"
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/b7745110d56fd24f.
Report an issue: GitHub.