From 5700c06689130fffcac24402bd1aa91e8bb03b28 Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Sat, 7 Mar 2026 17:06:29 -0800 Subject: [PATCH] fix(logging): fix turn_off_message_logging redaction for standard logging payload Two bugs in the redaction path for standard_logging_object["response"]: 1. get_final_response_obj was passing a plain dict (from model_dump()) into redact_message_input_output_from_logging. perform_redaction only handles ModelResponse/EmbeddingResponse/ResponsesAPIResponse -- a plain dict hits the else branch and returns {"text": "redacted-by-litellm"}, destroying the choices structure. Fix: pass init_response_obj (the original BaseModel) to redaction so isinstance checks work correctly, then call model_dump() on the result. 2. _redact_choice_content was not nulling choice.message.audio, so audio model responses (gpt-4o-audio-preview) kept the full audio blob in the logged payload even with turn_off_message_logging=True. Fix: set choice.message.audio = None alongside content redaction. Fixes: test_standard_logging_payload[True-ft:gpt-3.5-turbo:my-org:custom_suffix:id] test_standard_logging_payload_audio[True-False] test_standard_logging_payload_audio[True-True] --- litellm/litellm_core_utils/litellm_logging.py | 9 ++++++++- litellm/litellm_core_utils/redact_messages.py | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index 6f587abcdf1..335a0a1a940 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -4827,9 +4827,16 @@ class StandardLoggingPayloadSetup: else: final_response_obj = {} + # Pass the original BaseModel object to redaction so isinstance checks inside + # perform_redaction work correctly (a plain dict never matches ModelResponse etc.) + redaction_input = ( + init_response_obj + if isinstance(init_response_obj, BaseModel) + else final_response_obj + ) modified_final_response_obj = redact_message_input_output_from_logging( model_call_details=kwargs, - result=final_response_obj, + result=redaction_input, ) if modified_final_response_obj is not None and isinstance( diff --git a/litellm/litellm_core_utils/redact_messages.py b/litellm/litellm_core_utils/redact_messages.py index ad68f3851a8..cc41696c5ac 100644 --- a/litellm/litellm_core_utils/redact_messages.py +++ b/litellm/litellm_core_utils/redact_messages.py @@ -49,6 +49,8 @@ def _redact_choice_content(choice): choice.message.reasoning_content = "redacted-by-litellm" if hasattr(choice.message, "thinking_blocks"): choice.message.thinking_blocks = None + if hasattr(choice.message, "audio"): + choice.message.audio = None elif isinstance(choice, litellm.utils.StreamingChoices): choice.delta.content = "redacted-by-litellm" if hasattr(choice.delta, "reasoning_content"):