You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Flight][Fiber] Encode owner in the error payload in dev and use it as the Error's Task (#34460)
When we report an error we typically log the owner stack of the thing
that caught the error. Similarly we restore the `console.createTask`
scope of the catching component when we call `reportError` or
`console.error`.
We also have a special case if something throws during reconciliation
which uses the Server Component task as far as we got before we threw.
https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactChildFiber.js#L1952-L1960
Chrome has since fixed it (on our request) that the Error constructor
snapshots the Task at the time the constructor was created and logs that
in `reportError`. This is a good thing since it means we get a coherent
stack. Unfortunately, it means that the fake Errors that we create in
Flight Client gets a snapshot of the task where they were created so
when they're reported in the console they get the root Task instead of
the Task of the handler of the error.
Ideally we'd transfer the Task from the server and restore it. However,
since we don't instrument the Error object to snapshot the owner and we
can't read the native Task (if it's even enabled on the server) we don't
actually have a correct snapshot to transfer for a Server Component
Error. However, we can use the parent's task for where the error was
observed by Flight Server and then encode that as a pseudo owner of the
Error.
Then we use this owner as the Task which the Error is created within.
Now the client snapshots that Task which is reported by `reportError` so
now we have an async stack for Server Component errors again. (Note that
this owner may differ from the one observed by `captureOwnerStack` which
gets the nearest Server Component from where it was caught. We could
attach the owner to the Error object and use that owner when calling
`onCaughtError`/`onUncaughtError`).
Before:
<img width="911" height="57" alt="Screenshot 2025-09-10 at 10 57 54 AM"
src="https://github.com/user-attachments/assets/0446ef96-fad9-4e17-8a9a-d89c334233ec"
/>
After:
<img width="910" height="128" alt="Screenshot 2025-09-10 at 11 06 20 AM"
src="https://github.com/user-attachments/assets/b30e5892-cf40-4246-a588-0f309575439b"
/>
Similarly, there are Errors and warnings created by ChildFiber itself.
Those execute in the scope of the general render of the parent Fiber.
They used to get the scope of the nearest client component parent (e.g.
div in this case) but that's the parent of the Server Component. It
would be too expensive to run every level of reconciliation in its own
task optimistically, so this does it only when we know that we'll throw
or log an error that needs this context. Unfortunately this doesn't
cover user space errors (such as if an iterable errors).
Before:
<img width="903" height="298" alt="Screenshot 2025-09-10 at 11 31 55 AM"
src="https://github.com/user-attachments/assets/cffc94da-8c14-4d6e-9a5b-bf0833b8b762"
/>
After:
<img width="1216" height="252" alt="Screenshot 2025-09-10 at 11 50
54 AM"
src="https://github.com/user-attachments/assets/f85f93cf-ab73-4046-af3d-dd93b73b3552"
/>
<img width="412" height="115" alt="Screenshot 2025-09-10 at 11 52 46 AM"
src="https://github.com/user-attachments/assets/a76cef7b-b162-4ecf-9b0a-68bf34afc239"
/>
DiffTrain build for [20e5431](20e5431)
Copy file name to clipboardExpand all lines: compiled/facebook-www/ReactART-dev.classic.js
+40-6Lines changed: 40 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -3784,6 +3784,16 @@ __DEV__ &&
3784
3784
: previousDebugInfo.concat(debugInfo));
3785
3785
return previousDebugInfo;
3786
3786
}
3787
+
function getCurrentDebugTask() {
3788
+
var debugInfo = currentDebugInfo;
3789
+
if (null != debugInfo)
3790
+
for (var i = debugInfo.length - 1; 0 <= i; i--)
3791
+
if (null != debugInfo[i].name) {
3792
+
var debugTask = debugInfo[i].debugTask;
3793
+
if (null != debugTask) return debugTask;
3794
+
}
3795
+
return null;
3796
+
}
3787
3797
function validateFragmentProps(element, fiber, returnFiber) {
3788
3798
for (var keys = Object.keys(element.props), i = 0; i < keys.length; i++) {
3789
3799
var key = keys[i];
@@ -3825,7 +3835,7 @@ __DEV__ &&
3825
3835
element = element.props.ref;
3826
3836
workInProgress.ref = void 0 !== element ? element : null;
3827
3837
}
3828
-
function throwOnInvalidObjectType(returnFiber, newChild) {
3838
+
function throwOnInvalidObjectTypeImpl(returnFiber, newChild) {
3829
3839
if (newChild.$$typeof === REACT_LEGACY_ELEMENT_TYPE)
3830
3840
throw Error(
3831
3841
'A React Element from an older version of React was rendered. This is not supported. It can happen if:\n- Multiple copies of the "react" package is used.\n- A library pre-bundled an old copy of "react" or "react/jsx-runtime".\n- A compiler tries to "inline" JSX instead of using the runtime.'
@@ -3839,7 +3849,15 @@ __DEV__ &&
3839
3849
"). If you meant to render a collection of children, use an array instead."
3840
3850
);
3841
3851
}
3842
-
function warnOnFunctionType(returnFiber, invalidChild) {
3852
+
function throwOnInvalidObjectType(returnFiber, newChild) {
Copy file name to clipboardExpand all lines: compiled/facebook-www/ReactART-dev.modern.js
+40-6Lines changed: 40 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -3690,6 +3690,16 @@ __DEV__ &&
3690
3690
: previousDebugInfo.concat(debugInfo));
3691
3691
return previousDebugInfo;
3692
3692
}
3693
+
function getCurrentDebugTask() {
3694
+
var debugInfo = currentDebugInfo;
3695
+
if (null != debugInfo)
3696
+
for (var i = debugInfo.length - 1; 0 <= i; i--)
3697
+
if (null != debugInfo[i].name) {
3698
+
var debugTask = debugInfo[i].debugTask;
3699
+
if (null != debugTask) return debugTask;
3700
+
}
3701
+
return null;
3702
+
}
3693
3703
function validateFragmentProps(element, fiber, returnFiber) {
3694
3704
for (var keys = Object.keys(element.props), i = 0; i < keys.length; i++) {
3695
3705
var key = keys[i];
@@ -3731,7 +3741,7 @@ __DEV__ &&
3731
3741
element = element.props.ref;
3732
3742
workInProgress.ref = void 0 !== element ? element : null;
3733
3743
}
3734
-
function throwOnInvalidObjectType(returnFiber, newChild) {
3744
+
function throwOnInvalidObjectTypeImpl(returnFiber, newChild) {
3735
3745
if (newChild.$$typeof === REACT_LEGACY_ELEMENT_TYPE)
3736
3746
throw Error(
3737
3747
'A React Element from an older version of React was rendered. This is not supported. It can happen if:\n- Multiple copies of the "react" package is used.\n- A library pre-bundled an old copy of "react" or "react/jsx-runtime".\n- A compiler tries to "inline" JSX instead of using the runtime.'
@@ -3745,7 +3755,15 @@ __DEV__ &&
3745
3755
"). If you meant to render a collection of children, use an array instead."
3746
3756
);
3747
3757
}
3748
-
function warnOnFunctionType(returnFiber, invalidChild) {
3758
+
function throwOnInvalidObjectType(returnFiber, newChild) {
0 commit comments