diff --git a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py index 416444664a3..01aa8465567 100644 --- a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py +++ b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py @@ -1742,10 +1742,11 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints): continue for c in content: if c.get("type") == "file": - file_object = cast(ChatCompletionFileObject, c) - file_object_file_field = file_object["file"] + file_object_file_field = cast(Dict[str, object], c).get("file") + if not isinstance(file_object_file_field, dict): + continue file_id = file_object_file_field.get("file_id") - if file_id: + if isinstance(file_id, str) and file_id: file_ids.append(file_id) return file_ids diff --git a/tests/unit/enterprise/proxy/hooks/test_managed_files.py b/tests/unit/enterprise/proxy/hooks/test_managed_files.py index 7f6e955e831..33d7289c893 100644 --- a/tests/unit/enterprise/proxy/hooks/test_managed_files.py +++ b/tests/unit/enterprise/proxy/hooks/test_managed_files.py @@ -332,6 +332,26 @@ def test_get_file_ids_from_messages_skips_bedrock_content_blocks_without_type(): assert file_ids == ["file-keep"] +def test_get_file_ids_from_messages_leaves_malformed_file_parts_to_request_validation(): + proxy_managed_files = PROXY_LiteLLMManagedFiles( + DualCache(), prisma_client=MagicMock() + ) + messages = [ + { + "role": "user", + "content": [ + {"type": "file"}, + {"type": "file", "file": "file-raw"}, + {"type": "file", "file": None}, + {"type": "file", "file": {"file_id": 7}}, + {"type": "file", "file": {"file_id": "file-keep"}}, + ], + } + ] + file_ids = proxy_managed_files.get_file_ids_from_messages(messages) + assert file_ids == ["file-keep"] + + @pytest.mark.asyncio async def test_async_pre_call_hook_batch_retrieve(): from litellm.proxy._types import UserAPIKeyAuth