diff --git a/packages/core/src/integrations/inboundfilters.ts b/packages/core/src/integrations/inboundfilters.ts index 161559874268..2dd87b5f91bf 100644 --- a/packages/core/src/integrations/inboundfilters.ts +++ b/packages/core/src/integrations/inboundfilters.ts @@ -71,6 +71,15 @@ function _shouldDropEvent(event: Event, options: Partial) ); return true; } + if (_isUselessError(event)) { + DEBUG_BUILD && + logger.warn( + `Event dropped due to not having an error message, error type or stacktrace.\nEvent: ${getEventDescription( + event, + )}`, + ); + return true; + } if (_isIgnoredTransaction(event, options.ignoreTransactions)) { DEBUG_BUILD && logger.warn( @@ -199,3 +208,22 @@ function _getEventFilterUrl(event: Event): string | null { return null; } } + +function _isUselessError(event: Event): boolean { + if (event.type) { + // event is not an error + return false; + } + + // We only want to consider events for dropping that actually have recorded exception values. + if (!event.exception || !event.exception.values || event.exception.values.length === 0) { + return false; + } + + return ( + // No top-level message + !event.message && + // There are no exception values that have a stacktrace, a non-generic-Error type or value + !event.exception.values.some(value => value.stacktrace || (value.type && value.type !== 'Error') || value.value) + ); +} diff --git a/packages/core/test/lib/integrations/inboundfilters.test.ts b/packages/core/test/lib/integrations/inboundfilters.test.ts index e4c46d18094f..eb68c8c14d3b 100644 --- a/packages/core/test/lib/integrations/inboundfilters.test.ts +++ b/packages/core/test/lib/integrations/inboundfilters.test.ts @@ -165,6 +165,66 @@ const EXCEPTION_EVENT_WITH_LINKED_ERRORS: Event = { }, }; +const USELESS_EXCEPTION_EVENT: Event = { + exception: { + values: [ + {}, + { + mechanism: { type: 'onunhandledrejection', handled: false }, + }, + ], + }, +}; + +const USELESS_ERROR_EXCEPTION_EVENT: Event = { + exception: { + values: [{ type: 'Error' }, {}], + }, +}; + +const EVENT_WITH_MESSAGE: Event = { + message: 'hello', +}; + +const EVENT_WITH_STACKTRACE: Event = { + exception: { + values: [ + {}, + { + stacktrace: { + frames: [ + { + abs_path: 'hello.js', + }, + ], + }, + }, + ], + }, +}; + +const EVENT_WITH_TYPE: Event = { + exception: { + values: [ + {}, + { + type: 'MyCustomError', + }, + ], + }, +}; + +const EVENT_WITH_VALUE: Event = { + exception: { + values: [ + {}, + { + value: 'some error', + }, + ], + }, +}; + const SENTRY_EVENT: Event = { exception: { values: [ @@ -511,4 +571,36 @@ describe('InboundFilters', () => { expect(eventProcessor(MESSAGE_EVENT_WITH_NATIVE_LAST_FRAME, {})).toBe(null); }); }); + + describe('useless errors', () => { + it("should drop event with exceptions that don't have any message, type or stack trace", () => { + const eventProcessor = createInboundFiltersEventProcessor(); + expect(eventProcessor(USELESS_EXCEPTION_EVENT, {})).toBe(null); + }); + + it('should drop event with just a generic error without stacktrace or message', () => { + const eventProcessor = createInboundFiltersEventProcessor(); + expect(eventProcessor(USELESS_ERROR_EXCEPTION_EVENT, {})).toBe(null); + }); + + it('should not drop event with a message', () => { + const eventProcessor = createInboundFiltersEventProcessor(); + expect(eventProcessor(EVENT_WITH_MESSAGE, {})).toBe(EVENT_WITH_MESSAGE); + }); + + it('should not drop event with an exception that has a type', () => { + const eventProcessor = createInboundFiltersEventProcessor(); + expect(eventProcessor(EVENT_WITH_TYPE, {})).toBe(EVENT_WITH_TYPE); + }); + + it('should not drop event with an exception that has a stacktrace', () => { + const eventProcessor = createInboundFiltersEventProcessor(); + expect(eventProcessor(EVENT_WITH_STACKTRACE, {})).toBe(EVENT_WITH_STACKTRACE); + }); + + it('should not drop event with an exception that has a value', () => { + const eventProcessor = createInboundFiltersEventProcessor(); + expect(eventProcessor(EVENT_WITH_VALUE, {})).toBe(EVENT_WITH_VALUE); + }); + }); });