diff --git a/litellm/litellm_core_utils/prompt_templates/common_utils.py b/litellm/litellm_core_utils/prompt_templates/common_utils.py index 748347fe938..c36e5dd750b 100644 --- a/litellm/litellm_core_utils/prompt_templates/common_utils.py +++ b/litellm/litellm_core_utils/prompt_templates/common_utils.py @@ -1313,7 +1313,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 44f91c98d81..9ff47f49309 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