Description
The /product/search API returns 0 results for certain memory cubes despite the data being correctly stored in both Qdrant and Neo4j. The issue specifically affects cubes with smaller memory counts while cubes with larger counts work correctly.
Environment
- MemOS version: 1.0.1 (Docker)
- Embedding model: qwen3-embedding:8b (4096-dim)
- Vector DB: Qdrant v1.15.3
- Graph DB: Neo4j 5.26.6
- Deployment: Docker Compose on macOS (M4 Pro)
Steps to Reproduce
- Create multiple memory cubes with varying sizes
- Store memories in each cube via
/product/add
- Search each cube via
/product/search with correct parameters
Expected Behavior
All cubes with stored memories should return relevant results.
Actual Behavior
| Cube |
Memories (Neo4j) |
Memories (Qdrant) |
Search Results |
| hermes-shared |
2,911 |
2,911 |
✓ 3 results |
| hermes-mac-mini-private |
29 |
27 |
✓ 3 results |
| hermes-ubuntu-private |
93 |
93 |
✗ 0 results |
| hermes-worklab-private |
64 |
64 |
✗ 0 results |
Investigation Findings
1. Data integrity verified
All data exists in both Neo4j and Qdrant with correct metadata:
Neo4j memory types:
hermes-shared: 2482 LongTermMemory + 429 UserMemory
hermes-ubuntu-private: 83 LongTermMemory + 10 UserMemory
hermes-worklab-private: 3 LongTermMemory + 61 UserMemory
hermes-mac-mini-private: 21 LongTermMemory + 8 UserMemory
Qdrant: 3098 total points, all with 4096-dim vectors and correct user_name filters.
2. Direct Qdrant vector search works for ALL cubes
Direct vector search via Qdrant REST API returns correct results for ALL cubes, including the affected ones. The vectors and metadata are intact.
3. Search pipeline analysis
The search flow in searcher.py → _retrieve_paths() runs these in parallel:
_retrieve_from_working_memory → Neo4j query for WorkingMemory (0 entries exist for any cube)
_retrieve_from_long_term_and_user → Should do vector search for LongTermMemory/UserMemory
_retrieve_from_internet → Internet search
_retrieve_from_keyword → Fulltext search
4. Critical finding: _vector_recall method missing
In recall.py, the GraphMemoryRetriever class references self._vector_recall at lines 144, 212, and 232, but no such method exists on the class. Only _vector_recall_ORIGINAL is defined (line 370):
# Line 144 - calls self._vector_recall
future_vector = executor.submit(
self._vector_recall, # ← This method doesn't exist!
query_embedding or [],
memory_scope,
top_k,
...
)
# Line 370 - only this method exists
def _vector_recall_ORIGINAL(self, query_embedding, memory_scope, ...):
# ... actual vector search implementation
Verified at runtime:
>>> from memos.memories.textual.tree_text_memory.retrieve.recall import GraphMemoryRetriever
>>> hasattr(GraphMemoryRetriever, '_vector_recall')
False
>>> hasattr(GraphMemoryRetriever, '_vector_recall_ORIGINAL')
True
5. API Request Used
POST /product/search
{
"query": "ubuntu infrastructure",
"user_id": "hermes-user",
"readable_cube_ids": ["hermes-ubuntu-private"],
"mode": "fast",
"top_k": 6,
"relativity": 0.35,
"dedup": "mmr",
"include_preference": false,
"search_tool_memory": false,
"include_skill_memory": false
}
Response for affected cubes: {"data": {"text_mem": []}}
Possible Root Cause
The _vector_recall method is referenced but undefined. The _vector_recall_ORIGINAL method contains the actual vector search implementation. Either:
_vector_recall was renamed to _vector_recall_ORIGINAL and the references weren't updated
- A wrapper/decorator that was supposed to create
_vector_recall from _vector_recall_ORIGINAL is not working
- There's a silent exception handling that masks the
AttributeError for some code paths
Suggested Fix
Rename _vector_recall_ORIGINAL back to _vector_recall, or update all references (lines 144, 212, 232) to use _vector_recall_ORIGINAL.
Description
The
/product/searchAPI returns 0 results for certain memory cubes despite the data being correctly stored in both Qdrant and Neo4j. The issue specifically affects cubes with smaller memory counts while cubes with larger counts work correctly.Environment
Steps to Reproduce
/product/add/product/searchwith correct parametersExpected Behavior
All cubes with stored memories should return relevant results.
Actual Behavior
Investigation Findings
1. Data integrity verified
All data exists in both Neo4j and Qdrant with correct metadata:
Qdrant: 3098 total points, all with 4096-dim vectors and correct
user_namefilters.2. Direct Qdrant vector search works for ALL cubes
Direct vector search via Qdrant REST API returns correct results for ALL cubes, including the affected ones. The vectors and metadata are intact.
3. Search pipeline analysis
The search flow in
searcher.py→_retrieve_paths()runs these in parallel:_retrieve_from_working_memory→ Neo4j query for WorkingMemory (0 entries exist for any cube)_retrieve_from_long_term_and_user→ Should do vector search for LongTermMemory/UserMemory_retrieve_from_internet→ Internet search_retrieve_from_keyword→ Fulltext search4. Critical finding:
_vector_recallmethod missingIn
recall.py, theGraphMemoryRetrieverclass referencesself._vector_recallat lines 144, 212, and 232, but no such method exists on the class. Only_vector_recall_ORIGINALis defined (line 370):Verified at runtime:
5. API Request Used
Response for affected cubes:
{"data": {"text_mem": []}}Possible Root Cause
The
_vector_recallmethod is referenced but undefined. The_vector_recall_ORIGINALmethod contains the actual vector search implementation. Either:_vector_recallwas renamed to_vector_recall_ORIGINALand the references weren't updated_vector_recallfrom_vector_recall_ORIGINALis not workingAttributeErrorfor some code pathsSuggested Fix
Rename
_vector_recall_ORIGINALback to_vector_recall, or update all references (lines 144, 212, 232) to use_vector_recall_ORIGINAL.