From 6bd10f8adf7708aefc1278200e907cff10dc7f18 Mon Sep 17 00:00:00 2001 From: yyobject <48043998+yyobject@users.noreply.github.com> Date: Tue, 27 Oct 2026 13:06:01 +0800 Subject: [PATCH] fix(anthropic): preserve attempt failure logging after main update --- .../pass_through_endpoints/streaming_handler.py | 15 +++++++++------ .../test_streaming_handler_interrupt.py | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/litellm/proxy/pass_through_endpoints/streaming_handler.py b/litellm/proxy/pass_through_endpoints/streaming_handler.py index 0feac6dc5ec..afc2d400fa8 100644 --- a/litellm/proxy/pass_through_endpoints/streaming_handler.py +++ b/litellm/proxy/pass_through_endpoints/streaming_handler.py @@ -408,11 +408,15 @@ class PassThroughStreamingHandler: request_mapping: Final = _REQUEST_BODY.validate_python(request_body) error_event: Final = parse_anthropic_error_event(complete_frames) if error_event is not None: - await AnthropicPassthroughLoggingHandler.log_error_frame_as_failure( - attempt_logging_obj=litellm_logging_obj, + error_type, message, status_code = error_event + await PassThroughStreamingHandler.schedule_stream_failure_logging( + litellm_logging_obj=litellm_logging_obj, + endpoint_type=endpoint_type, request_body=request_mapping, - all_chunks=raw_bytes, - error_event=error_event, + raw_bytes=raw_bytes, + exception=anthropic_error_frame_exception( + error_type, message, status_code, str(litellm_logging_obj.model) + ), ) return if not litellm_logging_obj.model_call_details["prompt_cache_response_complete"]: @@ -424,7 +428,7 @@ class PassThroughStreamingHandler: consumer_closed: Final = ( litellm_logging_obj.model_call_details.get("anthropic_stream_end") == "closed" ) - await litellm_logging_obj.dispatch_failure_handlers( + await litellm_logging_obj.dispatch_attempt_failure_handlers( litellm.APIError( status_code=499 if consumer_closed else 502, message=( @@ -436,7 +440,6 @@ class PassThroughStreamingHandler: model=str(litellm_logging_obj.model), ), "", - prefer_async_handlers=True, ) return # TinyFish billing is owned by the detached poller; the $0 fallback below is only for streams with no run_id diff --git a/tests/unit/proxy/pass_through_endpoints/test_streaming_handler_interrupt.py b/tests/unit/proxy/pass_through_endpoints/test_streaming_handler_interrupt.py index ebdc8ea8326..32d092c2ff7 100644 --- a/tests/unit/proxy/pass_through_endpoints/test_streaming_handler_interrupt.py +++ b/tests/unit/proxy/pass_through_endpoints/test_streaming_handler_interrupt.py @@ -759,6 +759,7 @@ async def test_chunk_processor_logs_failure_not_success_on_mid_stream_exception( def _anthropic_stream_dropping_after(frames: tuple[bytes, ...]) -> httpx.Response: mock: Final = MagicMock(spec=httpx.Response) mock.status_code = 200 + mock.headers = httpx.Headers() async def _aiter_bytes() -> AsyncIterator[bytes]: for frame in frames: