{"record":{"id":"b7745110d56fd24f","repo":"facebook/react","slug":"expected-overrideerror-to-not-get-called-for-ear","errorCode":null,"errorMessage":"Expected overrideError() to not get called for earlier React versions.","messagePattern":"Expected overrideError\\(\\) to not get called for earlier React versions\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-devtools-shared/src/backend/fiber/renderer.js","lineNumber":7412,"sourceCode":"      }\n      return inst.data.return;\n    } else {\n      return devtoolsInstance.data;\n    }\n  }\n\n  // React will switch between these implementations depending on whether\n  // we have any manually suspended/errored-out Fibers or not.\n  function shouldErrorFiberAlwaysNull() {\n    return null;\n  }\n\n  // Map of Fiber and its force error status: true (error), false (toggled off)\n  const forceErrorForFibers = new Map<Fiber, boolean>();\n\n  function shouldErrorFiberAccordingToMap(fiber: any): boolean | null {\n    if (typeof setErrorHandler !== 'function') {\n      throw new Error(\n        'Expected overrideError() to not get called for earlier React versions.',\n      );\n    }\n\n    let status = forceErrorForFibers.get(fiber);\n    if (status === false) {\n      // TRICKY overrideError adds entries to this Map,\n      // so ideally it would be the method that clears them too,\n      // but that would break the functionality of the feature,\n      // since DevTools needs to tell React to act differently than it normally would\n      // (don't just re-render the failed boundary, but reset its errored state too).\n      // So we can only clear it after telling React to reset the state.\n      // Technically this is premature and we should schedule it for later,\n      // since the render could always fail without committing the updated error boundary,\n      // but since this is a DEV-only feature, the simplicity is worth the trade off.\n      forceErrorForFibers.delete(fiber);\n      if (forceErrorForFibers.size === 0) {\n        // Last override is gone. Switch React back to fast path.","sourceCodeStart":7394,"sourceCodeEnd":7430,"githubUrl":"https://github.com/facebook/react/blob/eafeac097ba51e1eab809c07102126bd5f8e5425/packages/react-devtools-shared/src/backend/fiber/renderer.js#L7394-L7430","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before (custom DevTools integration)\nbridge.send('overrideError', {id, forceError: true, rendererID});\n\n// after - only when the renderer supports it\nconst renderer = hook.renderers.get(rendererID);\nif (typeof renderer?.setErrorHandler === 'function' && typeof renderer?.scheduleUpdate === 'function') {\n  bridge.send('overrideError', {id, forceError: true, rendererID});\n}","handlingStrategy":"validation","validationCode":"// enable error-override UI only when the renderer supports it (mirrors renderer.js:449-451)\nconst renderer = hook.renderers.get(rendererID);\nconst supportsTogglingError =\n  typeof renderer?.setErrorHandler === 'function' &&\n  typeof renderer?.scheduleUpdate === 'function';","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["react-devtools","error-boundary","version-mismatch","legacy-react"],"backgroundTag":"unsupported-react-version","analyzedSha":"eafeac097ba51e1eab809c07102126bd5f8e5425","analyzedAt":"2026-08-21T22:01:08.818Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}