Skip to content

Commit 5a33d8e

Browse files
committed
Improve error message when it's not a real message object
Also deals with symbols.
1 parent dc31781 commit 5a33d8e

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

packages/react-client/src/__tests__/ReactFlight-test.js

+90
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,96 @@ describe('ReactFlight', () => {
776776
});
777777
});
778778

779+
it('should emit descriptions of errors in dev', async () => {
780+
const ClientErrorBoundary = clientReference(ErrorBoundary);
781+
782+
function Throw({value}) {
783+
throw value;
784+
}
785+
786+
const testCases = (
787+
<>
788+
<ClientErrorBoundary expectedMessage="This is a real Error.">
789+
<div>
790+
<Throw value={new TypeError('This is a real Error.')} />
791+
</div>
792+
</ClientErrorBoundary>
793+
<ClientErrorBoundary expectedMessage="Error: This is a string error.">
794+
<div>
795+
<Throw value="This is a string error." />
796+
</div>
797+
</ClientErrorBoundary>
798+
<ClientErrorBoundary expectedMessage="Error: {message: ..., extra: ..., nested: ...}">
799+
<div>
800+
<Throw
801+
value={{
802+
message: 'This is a long message',
803+
extra: 'properties',
804+
nested: {more: 'prop'},
805+
}}
806+
/>
807+
</div>
808+
</ClientErrorBoundary>
809+
<ClientErrorBoundary
810+
expectedMessage={
811+
'Error: {message: "Short", extra: ..., nested: ...}'
812+
}>
813+
<div>
814+
<Throw
815+
value={{
816+
message: 'Short',
817+
extra: 'properties',
818+
nested: {more: 'prop'},
819+
}}
820+
/>
821+
</div>
822+
</ClientErrorBoundary>
823+
<ClientErrorBoundary expectedMessage="Error: Symbol(hello)">
824+
<div>
825+
<Throw value={Symbol('hello')} />
826+
</div>
827+
</ClientErrorBoundary>
828+
<ClientErrorBoundary expectedMessage="Error: 123">
829+
<div>
830+
<Throw value={123} />
831+
</div>
832+
</ClientErrorBoundary>
833+
<ClientErrorBoundary expectedMessage="Error: undefined">
834+
<div>
835+
<Throw value={undefined} />
836+
</div>
837+
</ClientErrorBoundary>
838+
<ClientErrorBoundary expectedMessage="Error: <div/>">
839+
<div>
840+
<Throw value={<div />} />
841+
</div>
842+
</ClientErrorBoundary>
843+
<ClientErrorBoundary expectedMessage="Error: function Foo() {}">
844+
<div>
845+
<Throw value={function Foo() {}} />
846+
</div>
847+
</ClientErrorBoundary>
848+
<ClientErrorBoundary expectedMessage={'Error: ["array"]'}>
849+
<div>
850+
<Throw value={['array']} />
851+
</div>
852+
</ClientErrorBoundary>
853+
</>
854+
);
855+
856+
const transport = ReactNoopFlightServer.render(testCases, {
857+
onError(x) {
858+
return __DEV__ ? 'a dev digest' : `digest("${x.message}")`;
859+
},
860+
});
861+
862+
await act(() => {
863+
startTransition(() => {
864+
ReactNoop.render(ReactNoopFlightClient.read(transport));
865+
});
866+
});
867+
});
868+
779869
it('should trigger the inner most error boundary inside a Client Component', async () => {
780870
function ServerComponent() {
781871
throw new Error('This was thrown in the Server Component.');

packages/react-server/src/ReactFlightServer.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1677,8 +1677,10 @@ function emitErrorChunk(
16771677
message = String(error.message);
16781678
// eslint-disable-next-line react-internal/safe-string-coercion
16791679
stack = String(error.stack);
1680+
} else if (typeof error === 'object' && error !== null) {
1681+
message = 'Error: ' + describeObjectForErrorMessage(error);
16801682
} else {
1681-
message = 'Error: ' + (error: any);
1683+
message = 'Error: ' + String(error);
16821684
}
16831685
} catch (x) {
16841686
message = 'An error occurred but serializing the error message failed.';

0 commit comments

Comments
 (0)