From 1212f858cb491d4a96530730f8b6866892d960b9 Mon Sep 17 00:00:00 2001 From: Codebuff Contributor Date: Thu, 14 May 2026 19:44:48 +0600 Subject: [PATCH] fix[devtools]: gracefully handle missing nodes in TREE_OPERATION_REMOVE instead of crashing When React re-renders components quickly (e.g., scrolling), tree operations can arrive out of order, causing TREE_OPERATION_REMOVE to try removing a node or referencing a parent that was already removed. The previous code called _throwAndEmitError which crashes the entire DevTools extension. This fix replaces the crash with a graceful skip: - Log a warning only in debug builds - Use 'continue' instead of 'break' to process remaining operations Fixes #33738, #25884 --- .../src/devtools/store.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/store.js b/packages/react-devtools-shared/src/devtools/store.js index e11b90272e59..e2da4c218a6c 100644 --- a/packages/react-devtools-shared/src/devtools/store.js +++ b/packages/react-devtools-shared/src/devtools/store.js @@ -1611,13 +1611,13 @@ export default class Store extends EventEmitter<{ const element = this._idToElement.get(id); if (element === undefined) { - this._throwAndEmitError( - Error( + if (__DEBUG__) { + console.warn( `Cannot remove node "${id}" because no matching node was found in the Store.`, - ), - ); + ); + } - break; + continue; } i += 1; @@ -1649,13 +1649,13 @@ export default class Store extends EventEmitter<{ parentElement = this._idToElement.get(parentID); if (parentElement === undefined) { - this._throwAndEmitError( - Error( + if (__DEBUG__) { + console.warn( `Cannot remove node "${id}" from parent "${parentID}" because no matching node was found in the Store.`, - ), - ); + ); + } - break; + continue; } const index = parentElement.children.indexOf(id);