diff --git a/litellm/litellm_core_utils/prompt_templates/factory.py b/litellm/litellm_core_utils/prompt_templates/factory.py index 4c3907dc52f..8ecab8e4056 100644 --- a/litellm/litellm_core_utils/prompt_templates/factory.py +++ b/litellm/litellm_core_utils/prompt_templates/factory.py @@ -1221,7 +1221,7 @@ def _gemini_tool_call_invoke_helper( "type": "object", } else: - arguments_dict = json.loads(arguments) + arguments_dict = parse_tool_call_arguments(arguments, tool_name=name, context="Gemini tool invoke") function_call: Final = VertexFunctionCall( name=name, args=arguments_dict, diff --git a/tests/unit/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py b/tests/unit/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py index d65f094971a..d7a72feee6d 100644 --- a/tests/unit/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py +++ b/tests/unit/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py @@ -1857,6 +1857,42 @@ def test_vertex_ai_transform_empty_function_call_arguments(): } + +@pytest.mark.parametrize( + "arguments, expected_args", + [ + (None, {}), + ('{"location": "Boston"', {"location": "Boston"}), + ], + ids=["null_arguments", "truncated_arguments"], +) +def test_convert_to_gemini_tool_call_invoke_tolerates_null_and_truncated_arguments(arguments, expected_args): + """ + Gemini conversion must accept the same tool call arguments as the Anthropic + path: null is treated as no arguments and truncated JSON is repaired, + instead of raising "Unable to convert openai tool calls". + """ + from litellm.litellm_core_utils.prompt_templates.factory import ( + convert_to_gemini_tool_call_invoke, + ) + + message = { + "role": "assistant", + "content": None, + "tool_calls": [ + { + "id": "call_1", + "type": "function", + "function": {"name": "get_weather", "arguments": arguments}, + } + ], + } + parts = convert_to_gemini_tool_call_invoke(message) + assert len(parts) == 1 + assert parts[0]["function_call"]["name"] == "get_weather" + assert parts[0]["function_call"]["args"] == expected_args + + @pytest.mark.asyncio async def test_bedrock_process_image_async_factory(): """