From bcc746d9b238d5e12ba28366fc80e29aff1f99ee Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Wed, 3 Apr 2024 16:28:47 -0400 Subject: [PATCH] Add a wrapper error around recovered concurrent errors --- .../react-dom/src/__tests__/ReactDOMFizzServer-test.js | 3 ++- packages/react-reconciler/src/ReactFiberThrow.js | 9 +++++++-- scripts/error-codes/codes.json | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js index 2c61eea519921..dab01e4bd9779 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js @@ -3297,7 +3297,8 @@ describe('ReactDOMFizzServer', () => { 'B', // Log the error - 'onRecoverableError: Oops!', + 'onRecoverableError: There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.', + 'Cause: Oops!', ]); // UI looks normal diff --git a/packages/react-reconciler/src/ReactFiberThrow.js b/packages/react-reconciler/src/ReactFiberThrow.js index c67ad951fc92f..8393e3d007a23 100644 --- a/packages/react-reconciler/src/ReactFiberThrow.js +++ b/packages/react-reconciler/src/ReactFiberThrow.js @@ -600,8 +600,12 @@ function throwException( // Otherwise, fall through to the error path. } - const errorInfo = createCapturedValueAtFiber(value, sourceFiber); - queueConcurrentError(errorInfo); + const wrapperError = new Error( + 'There was an error during concurrent rendering but React was able to recover by ' + + 'instead synchronously rendering the entire root.', + {cause: value}, + ); + queueConcurrentError(createCapturedValueAtFiber(wrapperError, sourceFiber)); renderDidError(); // We didn't find a boundary that could handle this type of exception. Start @@ -614,6 +618,7 @@ function throwException( return true; } + const errorInfo = createCapturedValueAtFiber(value, sourceFiber); let workInProgress: Fiber = returnFiber; do { switch (workInProgress.tag) { diff --git a/scripts/error-codes/codes.json b/scripts/error-codes/codes.json index d218b97a44878..b44eda5795c34 100644 --- a/scripts/error-codes/codes.json +++ b/scripts/error-codes/codes.json @@ -504,5 +504,6 @@ "516": "Attempted to call a temporary Client Reference from the server but it is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.", "517": "Symbols cannot be passed to a Server Function without a temporary reference set. Pass a TemporaryReferenceSet to the options.%s", "518": "Saw multiple hydration diff roots in a pass. This is a bug in React.", - "519": "Hydration Mismatch Exception: This is not a real error, and should not leak into userspace. If you're seeing this, it's likely a bug in React." + "519": "Hydration Mismatch Exception: This is not a real error, and should not leak into userspace. If you're seeing this, it's likely a bug in React.", + "520": "There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root." }