fix(memory): re-raise LLM extraction failures instead of returning [] (salvage of #5178) (#5878)

This commit is contained in:
Bartok
2026-07-01 07:06:19 -06:00
committed by GitHub
parent c325bd3b8e
commit ad7e09851c
2 changed files with 55 additions and 2 deletions
+46
View File
@@ -6,6 +6,7 @@ from unittest.mock import MagicMock, Mock
import pytest
from mem0.exceptions import LLMError
from mem0.memory.main import AsyncMemory, Memory
@@ -79,6 +80,28 @@ class TestAddToVectorStoreErrors:
assert mock_memory.llm.generate_response.call_count == 1
assert result == [] # Should return empty list when no memories processed
def test_llm_extraction_exception_is_reraised(self, mocker, mock_memory):
"""A provider error during fact extraction must propagate, not be swallowed.
Regression guard for the silent ``return []`` that made it impossible for
callers to tell "LLM unavailable" (429/5xx/timeout) from "no facts found".
Without the fix this raises AssertionError because the call returns [].
"""
class _ProviderError(Exception):
pass
mock_memory.llm.generate_response.side_effect = _ProviderError("429 rate limit")
mocker.patch("mem0.memory.main.capture_event")
with pytest.raises(LLMError) as exc_info:
mock_memory._add_to_vector_store(
messages=[{"role": "user", "content": "test"}], metadata={}, filters={}, infer=True
)
# The documented LLMError contract is honoured, and the original
# provider exception is preserved as the cause for debugging.
assert isinstance(exc_info.value.__cause__, _ProviderError)
class TestPromptOverridesCustomInstructions:
@pytest.fixture
@@ -245,6 +268,29 @@ class TestAsyncAddToVectorStoreErrors:
assert result == []
assert mock_async_memory.llm.generate_response.call_count == 1
@pytest.mark.asyncio
async def test_async_llm_extraction_exception_is_reraised(self, mock_async_memory, mocker):
"""Async counterpart of the sync re-raise guard.
A provider error during fact extraction must propagate as ``LLMError``
(with the original exception preserved as the cause), not be swallowed
into ``return []``. Without the fix a future revert of the async
``raise`` back to ``return []`` would pass the suite silently.
"""
mocker.patch("mem0.utils.factory.EmbedderFactory.create", return_value=MagicMock())
class _ProviderError(Exception):
pass
mock_async_memory.llm.generate_response.side_effect = _ProviderError("429 rate limit")
mocker.patch("mem0.memory.main.capture_event")
with pytest.raises(LLMError) as exc_info:
await mock_async_memory._add_to_vector_store(
messages=[{"role": "user", "content": "test"}], metadata={}, effective_filters={}, infer=True
)
assert isinstance(exc_info.value.__cause__, _ProviderError)
def _build_memory_instance(mocker, memory_cls):
_setup_mocks(mocker)