From 0e59e082137949ae5813c98df6db5acf7dd4f240 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 13 Oct 2026 11:05:17 +0200 Subject: [PATCH 1/3] fix(client-reports): Emit callback_error when a processor raises --- sentry_sdk/client.py | 8 ++------ sentry_sdk/scope.py | 32 +++++++++++++++++++++++++++----- tests/test_basics.py | 4 ++-- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index a804cfcd5e..ed637619b2 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -464,13 +464,9 @@ def _prepare_event( if scope is not None: event_ = scope.apply_to_event(event, hint, self.options) - # one of the event/error processors returned None + # one of the event/error processors returned None or raised; + # the client report is recorded in Scope._drop if event_ is None: - if self.transport: - self.transport.record_lost_event( - "event_processor", - data_category="error", - ) return None event = event_ diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 6df27c470f..0195d4de96 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -1458,8 +1458,16 @@ def _apply_user_attributes_to_telemetry( ): attributes[attribute_name] = self._user[user_attribute] - def _drop(self, cause: "Any", ty: str) -> "Optional[Any]": + def _drop( + self, cause: "Any", ty: str, exception_raised: bool = False + ) -> "Optional[Any]": logger.info("%s (%s) dropped event", ty, cause) + transport = sentry_sdk.get_client().transport + if transport: + transport.record_lost_event( + "callback_error" if exception_raised else "event_processor", + data_category="error", + ) return None def run_error_processors(self, event: "Event", hint: "Hint") -> "Optional[Event]": @@ -1476,10 +1484,17 @@ def run_error_processors(self, event: "Event", hint: "Hint") -> "Optional[Event] for error_processor in error_processors: new_event = None + exception_raised = False with capture_internal_exceptions(): - new_event = error_processor(event, exc_info) + try: + new_event = error_processor(event, exc_info) + except Exception: + exception_raised = True + raise if new_event is None: - return self._drop(error_processor, "error processor") + return self._drop( + error_processor, "error processor", exception_raised + ) event = new_event @@ -1506,10 +1521,17 @@ def run_event_processors(self, event: "Event", hint: "Hint") -> "Optional[Event] for event_processor in event_processors: new_event = None + exception_raised = False with capture_internal_exceptions(): - new_event = event_processor(event, hint) + try: + new_event = event_processor(event, hint) + except Exception: + exception_raised = True + raise if new_event is None: - return self._drop(event_processor, "event processor") + return self._drop( + event_processor, "event processor", exception_raised + ) event = new_event return event diff --git a/tests/test_basics.py b/tests/test_basics.py index a4baaa58dc..be41c03818 100644 --- a/tests/test_basics.py +++ b/tests/test_basics.py @@ -734,7 +734,7 @@ def bad_processor(event, hint): capture_message("should be dropped") assert len(events) == 0 - assert ("event_processor", "error", None, 1) in record_lost_event_calls + assert record_lost_event_calls == [("callback_error", "error", None, 1)] @pytest.mark.tests_internal_exceptions @@ -757,7 +757,7 @@ def bad_error_processor(event, exc_info): capture_exception() assert len(events) == 0 - assert ("event_processor", "error", None, 1) in record_lost_event_calls + assert record_lost_event_calls == [("callback_error", "error", None, 1)] @pytest.mark.tests_internal_exceptions From 35cede58a04d2bae19e7c8df61b8b49e3b2761df Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 13 Oct 2026 11:22:57 +0200 Subject: [PATCH 2/3] inline --- sentry_sdk/scope.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 0195d4de96..891ae8a148 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -1458,18 +1458,6 @@ def _apply_user_attributes_to_telemetry( ): attributes[attribute_name] = self._user[user_attribute] - def _drop( - self, cause: "Any", ty: str, exception_raised: bool = False - ) -> "Optional[Any]": - logger.info("%s (%s) dropped event", ty, cause) - transport = sentry_sdk.get_client().transport - if transport: - transport.record_lost_event( - "callback_error" if exception_raised else "event_processor", - data_category="error", - ) - return None - def run_error_processors(self, event: "Event", hint: "Hint") -> "Optional[Event]": """ Runs the error processors on the event and returns the modified event. @@ -1492,9 +1480,14 @@ def run_error_processors(self, event: "Event", hint: "Hint") -> "Optional[Event] exception_raised = True raise if new_event is None: - return self._drop( - error_processor, "error processor", exception_raised - ) + logger.info("%s (error processor) dropped event", error_processor) + transport = sentry_sdk.get_client().transport + if transport: + transport.record_lost_event( + "callback_error" if exception_raised else "event_processor", + data_category="error", + ) + return None event = new_event @@ -1529,9 +1522,17 @@ def run_event_processors(self, event: "Event", hint: "Hint") -> "Optional[Event] exception_raised = True raise if new_event is None: - return self._drop( - event_processor, "event processor", exception_raised + logger.info( + "%s (event processor processor) dropped event", event_processor ) + transport = sentry_sdk.get_client().transport + if transport: + transport.record_lost_event( + "callback_error" if exception_raised else "event_processor", + data_category="error", + ) + return None + event = new_event return event From 8d60cfa48a65812f588d71d34909ff7d3e71c246 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Tue, 13 Oct 2026 11:50:53 +0200 Subject: [PATCH 3/3] fix typo --- sentry_sdk/scope.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 891ae8a148..289e3059be 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -1522,9 +1522,7 @@ def run_event_processors(self, event: "Event", hint: "Hint") -> "Optional[Event] exception_raised = True raise if new_event is None: - logger.info( - "%s (event processor processor) dropped event", event_processor - ) + logger.info("%s (event processor) dropped event", event_processor) transport = sentry_sdk.get_client().transport if transport: transport.record_lost_event(