diff --git a/CHANGELOG.md b/CHANGELOG.md index 3225aa8b4b..234473b3d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ ### Features +- Add handling for HTTP 413 (Content Too Large) responses from Relay ([#5566](https://github.com/getsentry/sentry-react-native/issues/5566)) + - SDK now logs actionable error messages when envelopes are rejected due to size limits + - Prepared infrastructure to capture HTTP status codes from native transport layer for future enhancements - Add experimental `sentry-span-attributes` prop to attach custom attributes to user interaction spans ([#5569](https://github.com/getsentry/sentry-react-native/pull/5569)) ```tsx ; + ): Promise<{ status?: string; message?: string }>; captureScreenshot(): Promise; clearBreadcrumbs(): void; crash(): void; diff --git a/packages/core/src/js/wrapper.ts b/packages/core/src/js/wrapper.ts index 4089bc5c75..df7d7e77e2 100644 --- a/packages/core/src/js/wrapper.ts +++ b/packages/core/src/js/wrapper.ts @@ -218,7 +218,26 @@ export const NATIVE: SentryNativeWrapper = { envelopeBytes = newBytes; } - await RNSentry.captureEnvelope(base64StringFromByteArray(envelopeBytes), { hardCrashed }); + const response = await RNSentry.captureEnvelope(base64StringFromByteArray(envelopeBytes), { hardCrashed }); + + if (response?.status) { + const statusCode = parseInt(response.status, 10); + + // Handle HTTP 413 - Content Too Large + if (statusCode === 413) { + debug.error( + 'Failed to send event to Sentry: HTTP 413 - Envelope exceeds size limit.\n' + + 'The event was rejected because the envelope size exceeds the maximum allowed size.\n' + + 'Consider reducing the size of breadcrumbs, context data, or attachments.', + ); + } + // Log other error status codes + else if (statusCode >= 400) { + debug.error( + `Failed to send event to Sentry: HTTP ${statusCode}${response.message ? ` - ${response.message}` : ''}`, + ); + } + } }, /** diff --git a/packages/core/test/wrapper.test.ts b/packages/core/test/wrapper.test.ts index cc7b79c0d9..012b64a11d 100644 --- a/packages/core/test/wrapper.test.ts +++ b/packages/core/test/wrapper.test.ts @@ -696,6 +696,61 @@ describe('Tests Native Wrapper', () => { { hardCrashed: false }, ); }); + + test('handles HTTP 413 response from native', async () => { + const errorSpy = jest.spyOn(debug, 'error'); + + // Mock native module to return HTTP 413 + (RNSentry.captureEnvelope as jest.Mock).mockResolvedValueOnce({ + status: '413', + message: 'Payload Too Large', + }); + + const event = { + event_id: 'event0', + message: 'test', + }; + + const env = createEnvelope({ event_id: event.event_id, sent_at: '123' }, [ + [{ type: 'event' }, event] as EventItem, + ]); + + await NATIVE.sendEnvelope(env); + + expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('HTTP 413 - Envelope exceeds size limit')); + expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('Consider reducing the size of breadcrumbs')); + + errorSpy.mockRestore(); + // Reset mock to default behavior + (RNSentry.captureEnvelope as jest.Mock).mockResolvedValue({}); + }); + + test('handles other HTTP error responses from native', async () => { + const errorSpy = jest.spyOn(debug, 'error'); + + // Mock native module to return HTTP 400 + (RNSentry.captureEnvelope as jest.Mock).mockResolvedValueOnce({ + status: '400', + message: 'Bad Request', + }); + + const event = { + event_id: 'event0', + message: 'test', + }; + + const env = createEnvelope({ event_id: event.event_id, sent_at: '123' }, [ + [{ type: 'event' }, event] as EventItem, + ]); + + await NATIVE.sendEnvelope(env); + + expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('HTTP 400 - Bad Request')); + + errorSpy.mockRestore(); + // Reset mock to default behavior + (RNSentry.captureEnvelope as jest.Mock).mockResolvedValue({}); + }); }); describe('fetchRelease', () => {