From 2bddd403538e5e97d61589abf51e871762227343 Mon Sep 17 00:00:00 2001 From: daleselaji-dev Date: Fri, 21 Aug 2026 10:50:43 +0800 Subject: [PATCH] fix: preserve null content for tool call messages --- litellm/utils.py | 7 +++- .../test_message_normalization.py | 33 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/test_litellm/test_message_normalization.py diff --git a/litellm/utils.py b/litellm/utils.py index b8a9ea37e05..fb32cab51f9 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -7703,7 +7703,12 @@ def cleanup_none_field_in_message(message: AllMessageValues): remove None fields in the message - e.g. {"function": None} - some providers raise validation errors """ new_message: Final = message.copy() - return {k: v for k, v in new_message.items() if v is not None} + return { + k: v + for k, v in new_message.items() + if v is not None + or (k == "content" and new_message.get("role") == "assistant" and new_message.get("tool_calls")) + } def validate_chat_completion_user_messages(messages: list[AllMessageValues]): diff --git a/tests/test_litellm/test_message_normalization.py b/tests/test_litellm/test_message_normalization.py new file mode 100644 index 00000000000..9483ade4637 --- /dev/null +++ b/tests/test_litellm/test_message_normalization.py @@ -0,0 +1,33 @@ +from litellm.utils import cleanup_none_field_in_message + + +def test_cleanup_preserves_null_content_for_assistant_tool_calls(): + message = { + "role": "assistant", + "content": None, + "tool_calls": [ + { + "id": "call_1", + "type": "function", + "function": {"name": "get_weather", "arguments": "{}"}, + } + ], + } + + result = cleanup_none_field_in_message(message) + + assert result == message + assert "content" in result + + +def test_cleanup_still_removes_unneeded_null_fields(): + message = { + "role": "assistant", + "content": None, + "tool_calls": None, + "function_call": None, + } + + result = cleanup_none_field_in_message(message) + + assert result == {"role": "assistant"}