diff --git a/litellm/litellm_core_utils/prompt_templates/common_utils.py b/litellm/litellm_core_utils/prompt_templates/common_utils.py index 538d5f650ef..d2d32fe7c1c 100644 --- a/litellm/litellm_core_utils/prompt_templates/common_utils.py +++ b/litellm/litellm_core_utils/prompt_templates/common_utils.py @@ -1238,7 +1238,9 @@ def get_file_ids_from_messages(messages: List[AllMessageValues]) -> List[str]: if isinstance(content, str): continue for c in content: - if c["type"] == "file": + if not isinstance(c, dict): + continue + if c.get("type") == "file": file_object = cast(ChatCompletionFileObject, c) file_object_file_field = file_object.get("file") if not isinstance(file_object_file_field, dict): diff --git a/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_common_utils.py b/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_common_utils.py index 1b1db634ed2..7aa0d9898b2 100644 --- a/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_common_utils.py +++ b/tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_common_utils.py @@ -343,6 +343,32 @@ def test_get_file_ids_from_messages_file_field_not_dict(): assert get_file_ids_from_messages(messages) == [] +def test_get_file_ids_from_messages_content_block_without_type(): + """A content block dict that omits `type` must not raise KeyError.""" + messages = [ + { + "role": "user", + "content": [ + {"text": "hi"}, + {"type": "file", "file": {"file_id": "file-keep"}}, + ], + } + ] + + assert get_file_ids_from_messages(messages) == ["file-keep"] + + +def test_get_file_ids_from_messages_non_dict_content_items(): + """Non-dict content items (e.g. token-id lists forwarded by + text_completion, or bare strings) must be skipped, not indexed into.""" + messages = [ + {"role": "user", "content": [[1, 2, 3]]}, + {"role": "user", "content": ["hello"]}, + ] + + assert get_file_ids_from_messages(messages) == [] + + def test_update_messages_with_model_file_ids_skips_non_openai_file_blocks(): """`update_messages_with_model_file_ids` is also called on user content before provider dispatch. It must tolerate non-OpenAI file blocks the same