Skip to content

Commit

Permalink
Add a prefix to errors serialized from server rendering
Browse files Browse the repository at this point in the history
It can be a bit confusing to see where this error came from otherwise
since it didn't come from elsewhere on the client.
  • Loading branch information
sebmarkbage committed Mar 30, 2024
1 parent 73a50cb commit e4d2591
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 66 deletions.
62 changes: 44 additions & 18 deletions packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,8 @@ describe('ReactDOMFizzServer', () => {
errors,
[
[
theError.message,
'Switched to client rendering because the server rendering errored:\n\n' +
theError.message,
expectedDigest,
componentStack(['Lazy', 'Suspense', 'div', 'App']),
],
Expand Down Expand Up @@ -909,7 +910,8 @@ describe('ReactDOMFizzServer', () => {
errors,
[
[
theError.message,
'Switched to client rendering because the server rendering errored:\n\n' +
theError.message,
expectedDigest,
componentStack(['Lazy', 'Suspense', 'div', 'App']),
],
Expand Down Expand Up @@ -992,7 +994,8 @@ describe('ReactDOMFizzServer', () => {
errors,
[
[
theError.message,
'Switched to client rendering because the server rendering errored:\n\n' +
theError.message,
expectedDigest,
componentStack([
'Erroring',
Expand Down Expand Up @@ -1078,7 +1081,8 @@ describe('ReactDOMFizzServer', () => {
errors,
[
[
theError.message,
'Switched to client rendering because the server rendering errored:\n\n' +
theError.message,
expectedDigest,
componentStack(['Lazy', 'Suspense', 'div', 'App']),
],
Expand Down Expand Up @@ -1404,13 +1408,15 @@ describe('ReactDOMFizzServer', () => {
errors,
[
[
'The server did not finish this Suspense boundary: The render was aborted by the server without a reason.',
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'The render was aborted by the server without a reason.',
expectedDigest,
// We get the stack of the task when it was aborted which is why we see `h1`
componentStack(['h1', 'Suspense', 'div', 'App']),
],
[
'The server did not finish this Suspense boundary: The render was aborted by the server without a reason.',
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'The render was aborted by the server without a reason.',
expectedDigest,
componentStack(['Suspense', 'main', 'div', 'App']),
],
Expand Down Expand Up @@ -2145,7 +2151,8 @@ describe('ReactDOMFizzServer', () => {
errors,
[
[
theError.message,
'Switched to client rendering because the server rendering errored:\n\n' +
theError.message,
expectedDigest,
componentStack([
'AsyncText',
Expand Down Expand Up @@ -3431,12 +3438,14 @@ describe('ReactDOMFizzServer', () => {
errors,
[
[
'The server did not finish this Suspense boundary: foobar',
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'foobar',
'a digest',
componentStack(['Suspense', 'p', 'div', 'App']),
],
[
'The server did not finish this Suspense boundary: foobar',
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'foobar',
'a digest',
componentStack(['Suspense', 'span', 'div', 'App']),
],
Expand Down Expand Up @@ -3512,12 +3521,14 @@ describe('ReactDOMFizzServer', () => {
errors,
[
[
'The server did not finish this Suspense boundary: uh oh',
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'uh oh',
'a digest',
componentStack(['Suspense', 'p', 'div', 'App']),
],
[
'The server did not finish this Suspense boundary: uh oh',
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'uh oh',
'a digest',
componentStack(['Suspense', 'span', 'div', 'App']),
],
Expand Down Expand Up @@ -3991,7 +4002,8 @@ describe('ReactDOMFizzServer', () => {
errors,
[
[
theError.message,
'Switched to client rendering because the server rendering errored:\n\n' +
theError.message,
expectedDigest,
componentStack(['Erroring', 'Suspense', 'div', 'App']),
],
Expand Down Expand Up @@ -6772,7 +6784,14 @@ describe('ReactDOMFizzServer', () => {

expect(recoverableErrors).toEqual(
__DEV__
? ['server error', 'replay error', 'server error']
? [
'Switched to client rendering because the server rendering errored:\n\n' +
'server error',
'Switched to client rendering because the server rendering errored:\n\n' +
'replay error',
'Switched to client rendering because the server rendering errored:\n\n' +
'server error',
]
: [
'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',
'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',
Expand Down Expand Up @@ -6931,8 +6950,10 @@ describe('ReactDOMFizzServer', () => {
expect(recoverableErrors).toEqual(
__DEV__
? [
'The server did not finish this Suspense boundary: aborted',
'The server did not finish this Suspense boundary: aborted',
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'aborted',
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'aborted',
]
: [
'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',
Expand Down Expand Up @@ -7103,8 +7124,10 @@ describe('ReactDOMFizzServer', () => {
// It surfaced in two different suspense boundaries.
__DEV__
? [
'The server did not finish this Suspense boundary: replay error',
'The server did not finish this Suspense boundary: replay error',
'Switched to client rendering because the server rendering errored:\n\n' +
'replay error',
'Switched to client rendering because the server rendering errored:\n\n' +
'replay error',
]
: [
'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',
Expand Down Expand Up @@ -7230,7 +7253,10 @@ describe('ReactDOMFizzServer', () => {

expect(recoverableErrors).toEqual(
__DEV__
? ['server error']
? [
'Switched to client rendering because the server rendering errored:\n\n' +
'server error',
]
: [
'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',
],
Expand Down
20 changes: 12 additions & 8 deletions packages/react-dom/src/__tests__/ReactDOMHydrationDiff-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1292,10 +1292,12 @@ describe('ReactDOMServerHydration', () => {
}

expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Caught [The server did not finish this Suspense boundary: The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server]",
]
`);
[
"Caught [Switched to client rendering because the server rendering aborted due to:
The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server]",
]
`);
});

// @gate __DEV__
Expand All @@ -1318,10 +1320,12 @@ describe('ReactDOMServerHydration', () => {
}

expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Caught [The server did not finish this Suspense boundary: The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server]",
]
`);
[
"Caught [Switched to client rendering because the server rendering aborted due to:
The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToPipeableStream" which supports Suspense on the server]",
]
`);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2108,7 +2108,8 @@ describe('ReactDOMServerPartialHydration', () => {
});
if (__DEV__) {
await waitForAll([
'The server did not finish this Suspense boundary: The server used' +
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'The server used' +
' "renderToString" which does not support Suspense.',
]);
} else {
Expand Down Expand Up @@ -2177,7 +2178,8 @@ describe('ReactDOMServerPartialHydration', () => {
});
if (__DEV__) {
await waitForAll([
'The server did not finish this Suspense boundary: The server used' +
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'The server used' +
' "renderToString" which does not support Suspense.',
]);
} else {
Expand Down Expand Up @@ -2251,7 +2253,8 @@ describe('ReactDOMServerPartialHydration', () => {
});
if (__DEV__) {
await waitForAll([
'The server did not finish this Suspense boundary: The server used' +
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'The server used' +
' "renderToString" which does not support Suspense.',
]);
} else {
Expand Down Expand Up @@ -2571,7 +2574,8 @@ describe('ReactDOMServerPartialHydration', () => {
suspend = true;
if (__DEV__) {
await waitForAll([
'The server did not finish this Suspense boundary: The server used' +
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'The server used' +
' "renderToString" which does not support Suspense.',
]);
} else {
Expand Down Expand Up @@ -2641,7 +2645,8 @@ describe('ReactDOMServerPartialHydration', () => {
});
if (__DEV__) {
await waitForAll([
'The server did not finish this Suspense boundary: The server used' +
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'The server used' +
' "renderToString" which does not support Suspense.',
]);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,8 @@ describe('ReactDOMServerHydration', () => {
expect(errors.length).toBe(1);
if (__DEV__) {
expect(errors[0]).toBe(
'The server did not finish this Suspense boundary: The server used "renderToString" ' +
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'The server used "renderToString" ' +
'which does not support Suspense. If you intended for this Suspense boundary to render ' +
'the fallback content on the server consider throwing an Error somewhere within the ' +
'Suspense boundary. If you intended to have the server wait for the suspended component ' +
Expand Down Expand Up @@ -726,7 +727,8 @@ describe('ReactDOMServerHydration', () => {
expect(errors.length).toBe(1);
if (__DEV__) {
expect(errors[0]).toBe(
'The server did not finish this Suspense boundary: The server used "renderToString" ' +
'Switched to client rendering because the server rendering aborted due to:\n\n' +
'The server used "renderToString" ' +
'which does not support Suspense. If you intended for this Suspense boundary to render ' +
'the fallback content on the server consider throwing an Error somewhere within the ' +
'Suspense boundary. If you intended to have the server wait for the suspended component ' +
Expand Down
8 changes: 4 additions & 4 deletions packages/react-reconciler/src/ReactFiberBeginWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -2659,18 +2659,18 @@ function updateDehydratedSuspenseComponent(
// TODO: Figure out a better signal than encoding a magic digest value.
if (!enablePostpone || digest !== 'POSTPONE') {
let error;
if (message) {
if (__DEV__ && message) {
// eslint-disable-next-line react-internal/prod-error-codes
error = new Error(message);
} else {
error = new Error(
'The server could not finish this Suspense boundary, likely ' +
'due to an error during server rendering. Switched to ' +
'client rendering.',
'due to an error during server rendering. ' +
'Switched to client rendering.',
);
}
// Replace the stack with the server stack
error.stack = stack || '';
error.stack = (__DEV__ && stack) || '';
(error: any).digest = digest;
capturedValue = createCapturedValueFromError(
error,
Expand Down
Loading

0 comments on commit e4d2591

Please sign in to comment.