From 8a1c7b82ad5631aafdc2cccf5f65f3df115d5026 Mon Sep 17 00:00:00 2001 From: Chau Vu / CPF-FAMILY Date: Tue, 27 Oct 2026 14:44:09 +0700 Subject: [PATCH] fix(redact_messages): guard against None output_items in Responses API redaction helpers - Add early return guard for None or empty output_items in _redact_responses_api_output - Add early return guard for None or empty output_items in _redact_responses_api_output_dict - Add unit test verifying perform_redaction and helpers safely handle None output - Fixes #43797 --- litellm/litellm_core_utils/redact_messages.py | 6 +++++- .../test_redact_messages.py | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/litellm/litellm_core_utils/redact_messages.py b/litellm/litellm_core_utils/redact_messages.py index 7f8a38cc8ec..3421791ee4a 100644 --- a/litellm/litellm_core_utils/redact_messages.py +++ b/litellm/litellm_core_utils/redact_messages.py @@ -219,6 +219,8 @@ def _redact_field_when_present(item: object, field: str) -> None: def _redact_responses_api_output(output_items): """Helper to redact ResponsesAPIResponse output items.""" + if not output_items: + return for output_item in output_items: output_type = stream_item_field(output_item, "type") if getattr(output_item, "text", None) is not None: @@ -295,7 +297,9 @@ def _redacted_responses_api_output_item(item: object, redacted_str: str) -> obje } -def _redact_responses_api_output_dict(output_items: Sequence[object], redacted_str: str) -> Sequence[object]: +def _redact_responses_api_output_dict(output_items: Sequence[object] | None, redacted_str: str) -> Sequence[object]: + if not output_items: + return [] return [_redacted_responses_api_output_item(item, redacted_str) for item in output_items] diff --git a/tests/unit/litellm_core_utils/test_redact_messages.py b/tests/unit/litellm_core_utils/test_redact_messages.py index 6a734ca3b70..38962c55260 100644 --- a/tests/unit/litellm_core_utils/test_redact_messages.py +++ b/tests/unit/litellm_core_utils/test_redact_messages.py @@ -899,6 +899,26 @@ class TestPerformRedaction: assert none_dict == {"type": "output_text", "text": None, "content": [{"text": None}]} assert real_dict == {"type": "output_text", "text": "real answer", "content": [{"text": "real part"}]} + def test_redact_responses_api_output_handles_none(self): + from litellm.litellm_core_utils.redact_messages import ( + _redact_responses_api_output, + _redact_responses_api_output_dict, + _redact_streaming_response, + ) + + _redact_responses_api_output(None) + assert _redact_responses_api_output_dict(None, "redacted-by-litellm") == [] + + # Test dictionary output: None + result_dict = {"output": None} + redacted_dict = perform_redaction({}, result_dict) + assert redacted_dict["output"] is None + + # Test object/streaming response output: None + streaming_obj = SimpleNamespace(output=None) + _redact_streaming_response(streaming_obj) + assert streaming_obj.output is None + def test_skips_non_dict_response_output_items(self): result = { "output": [