From 2025e607c5c8851474af40d069b92b2744565e04 Mon Sep 17 00:00:00 2001 From: Alexander Pantiukhov Date: Tue, 27 Jan 2026 15:45:03 +0100 Subject: [PATCH 1/2] SDK Handling HTTP 413 --- CHANGELOG.md | 3 + .../io/sentry/react/RNSentryModuleImpl.java | 11 +++- packages/core/ios/RNSentry.mm | 4 +- packages/core/src/js/NativeRNSentry.ts | 2 +- packages/core/src/js/wrapper.ts | 21 ++++++- packages/core/test/wrapper.test.ts | 55 +++++++++++++++++++ 6 files changed, 90 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbfb633f8d..4c315dc57b 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', () => { From 8cacfd3a433b8108bb2d5815ca8901ca491d5188 Mon Sep 17 00:00:00 2001 From: Alexander Pantiukhov Date: Tue, 27 Jan 2026 15:45:17 +0100 Subject: [PATCH 2/2] Code fix --- packages/core/ios/RNSentry.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/ios/RNSentry.mm b/packages/core/ios/RNSentry.mm index 27fb9a76de..b2b596c315 100644 --- a/packages/core/ios/RNSentry.mm +++ b/packages/core/ios/RNSentry.mm @@ -557,7 +557,7 @@ - (void)stopObserving #endif // TODO(alwx): Capture transport response from sentry-cocoa when available - resolve(@{}); + resolve(@ {}); } RCT_EXPORT_METHOD(