diff --git a/packages/react/src/errorboundary.tsx b/packages/react/src/errorboundary.tsx index 9a01ae110a64..bc613c87172f 100644 --- a/packages/react/src/errorboundary.tsx +++ b/packages/react/src/errorboundary.tsx @@ -1,6 +1,6 @@ import type { ReportDialogOptions, Scope } from '@sentry/browser'; import { captureException, getCurrentHub, showReportDialog, withScope } from '@sentry/browser'; -import { isError, logger } from '@sentry/utils'; +import { isError, logger, truncate } from '@sentry/utils'; import hoistNonReactStatics from 'hoist-non-react-statics'; import * as React from 'react'; @@ -10,6 +10,7 @@ export function isAtLeastReact17(version: string): boolean { } export const UNKNOWN_COMPONENT = 'unknown'; +const MAX_VALUE_LENGTH = 250; export type FallbackRender = (errorData: { error: Error; @@ -79,6 +80,7 @@ function setCause(error: Error & { cause?: Error }, cause: Error): void { seenErrors.set(error, true); return recurse(error.cause, cause); } + cause.message = truncate(cause.message, MAX_VALUE_LENGTH); error.cause = cause; } diff --git a/packages/react/test/errorboundary.test.tsx b/packages/react/test/errorboundary.test.tsx index f90aaa04b346..ef97e07723f2 100644 --- a/packages/react/test/errorboundary.test.tsx +++ b/packages/react/test/errorboundary.test.tsx @@ -382,6 +382,43 @@ describe('ErrorBoundary', () => { expect(cause.name).not.toContain('React ErrorBoundary'); }); + it('should truncate cause.message to 250 characters', () => { + const mockOnError = jest.fn(); + + function CustomBam(): JSX.Element { + const error = new Error('bam'); + // The cause message with 610 characters + const cause = new Error('This is a very long cause message that exceeds 250 characters '.repeat(10)); + // @ts-ignore Need to set cause on error + error.cause = cause; + throw error; + } + + render( + You have hit an error

} onError={mockOnError} errorComp={}> +

children

+
, + ); + + expect(mockOnError).toHaveBeenCalledTimes(0); + expect(mockCaptureException).toHaveBeenCalledTimes(0); + + const btn = screen.getByTestId('errorBtn'); + fireEvent.click(btn); + + expect(mockCaptureException).toHaveBeenCalledTimes(1); + expect(mockCaptureException).toHaveBeenLastCalledWith(expect.any(Error), { + contexts: { react: { componentStack: expect.any(String) } }, + }); + + expect(mockOnError.mock.calls[0][0]).toEqual(mockCaptureException.mock.calls[0][0]); + + const error = mockCaptureException.mock.calls[0][0]; + const cause = error.cause; + // We need to make sure that the length of the cause message is 250 + expect(cause.message).toHaveLength(250); + }); + it('calls `beforeCapture()` when an error occurs', () => { const mockBeforeCapture = jest.fn();