diff --git a/mem0-ts/src/oss/src/utils/memory.ts b/mem0-ts/src/oss/src/utils/memory.ts index 832809369..26c18c730 100644 --- a/mem0-ts/src/oss/src/utils/memory.ts +++ b/mem0-ts/src/oss/src/utils/memory.ts @@ -31,9 +31,11 @@ const parse_vision_messages = async (messages: Message[]) => { typeof message.content === "object" && message.content.type === "image_url" ) { - const description = await get_image_description( - message.content.image_url.url, - ); + const imageUrl = message.content.image_url?.url; + if (!imageUrl) { + throw new Error("image_url content part is missing image_url.url"); + } + const description = await get_image_description(imageUrl); new_message.content = typeof description === "string" ? description diff --git a/mem0/memory/utils.py b/mem0/memory/utils.py index dbfd3384d..dd7b1e4cc 100644 --- a/mem0/memory/utils.py +++ b/mem0/memory/utils.py @@ -206,7 +206,10 @@ def parse_vision_messages(messages, llm=None, vision_details="auto"): elif isinstance(content, dict) and content.get("type") == "image_url": if llm is None: continue - image_url = content["image_url"]["url"] + image_url_obj = content.get("image_url") + image_url = image_url_obj.get("url") if isinstance(image_url_obj, dict) else None + if not image_url: + raise ValueError("image_url content part is missing image_url.url") try: description = get_image_description(image_url, llm, vision_details) returned_messages.append({"role": role, "content": description}) diff --git a/tests/memory/test_memory_utils.py b/tests/memory/test_memory_utils.py index 820729133..49c55c5cb 100644 --- a/tests/memory/test_memory_utils.py +++ b/tests/memory/test_memory_utils.py @@ -96,6 +96,24 @@ class TestParseVisionMessages: result = parse_vision_messages(messages, llm=None) assert result == messages + def test_malformed_image_dict_raises_value_error(self): + # A malformed image part (missing the nested url) used to raise an + # uncaught KeyError that aborted add(); it should raise a clear ValueError. + mock_llm = Mock() + messages = [{"role": "user", "content": {"type": "image_url", "image_url": {}}}] + with pytest.raises(ValueError, match=r"missing image_url\.url"): + parse_vision_messages(messages, llm=mock_llm) + mock_llm.generate_response.assert_not_called() + + def test_none_image_url_raises_value_error(self): + # image_url present but None (or any non-dict) must also raise the clear + # ValueError, not an AttributeError from calling .get() on None. + mock_llm = Mock() + messages = [{"role": "user", "content": {"type": "image_url", "image_url": None}}] + with pytest.raises(ValueError, match=r"missing image_url\.url"): + parse_vision_messages(messages, llm=mock_llm) + mock_llm.generate_response.assert_not_called() + class TestRemoveSpacesFromEntities: """