From 9cd6b58bc874884195719ecfc7fa99ee480fc209 Mon Sep 17 00:00:00 2001 From: Harshit28j Date: Fri, 6 Mar 2026 04:27:33 +0530 Subject: [PATCH] fix: prevent duplicate failure callbacks for pass-through endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sync failure_handler was calling log_failure_event() for CustomLogger instances on pass-through endpoint failures, while async_failure_handler also called async_log_failure_event() — causing duplicate Datadog/Arize logs. Add the same call_type != pass_through guard that already exists in the success handler. Also pass the existing logging_obj in request_payload so _handle_logging_proxy_only_error preserves the correct call_type. Co-Authored-By: Claude Opus 4.6 --- litellm/litellm_core_utils/litellm_logging.py | 3 +-- .../pass_through_endpoints.py | 13 ++++--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index 6f2d8f531b5..6fa279dcbf5 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -2922,8 +2922,7 @@ class Logging(LiteLLMLoggingBaseClass): if ( isinstance(callback, CustomLogger) and is_sync_request - and self.call_type - != CallTypes.pass_through.value # pass-through endpoints call async_log_failure_event + and (self.call_type != CallTypes.pass_through.value) # pass-through endpoints call async_log_failure_event ): # custom logger class callback.log_failure_event( start_time=start_time, diff --git a/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py b/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py index c3102e36e3e..5b4166d0979 100644 --- a/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py +++ b/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py @@ -646,6 +646,7 @@ async def pass_through_request( # noqa: PLR0915 _parsed_body: Optional[dict] = None # kwargs for pass through endpoint, contains metadata, litellm_params, call_type, litellm_call_id, passthrough_logging_payload kwargs: Optional[dict] = None + logging_obj: Optional[Logging] = None ######################################################### try: @@ -959,10 +960,8 @@ async def pass_through_request( # noqa: PLR0915 # Pass the existing logging_obj so _handle_logging_proxy_only_error # uses it (preserves call_type="pass_through_endpoint" for dedup) - try: + if logging_obj is not None: request_payload["litellm_logging_obj"] = logging_obj - except NameError: - pass await proxy_logging_obj.post_call_failure_hook( user_api_key_dict=user_api_key_dict, @@ -1705,10 +1704,8 @@ async def websocket_passthrough_request( # noqa: PLR0915 request_payload[key] = value # Pass the existing logging_obj (preserves call_type for dedup) - try: + if logging_obj is not None: request_payload["litellm_logging_obj"] = logging_obj - except NameError: - pass # Log the connection failure using the same pattern as HTTP await proxy_logging_obj.post_call_failure_hook( @@ -1737,10 +1734,8 @@ async def websocket_passthrough_request( # noqa: PLR0915 request_payload[key] = value # Pass the existing logging_obj (preserves call_type for dedup) - try: + if logging_obj is not None: request_payload["litellm_logging_obj"] = logging_obj - except NameError: - pass # Log the unexpected error using the same pattern as HTTP await proxy_logging_obj.post_call_failure_hook(