From 8005e18aec2516ac6fb162c816c7fe9a1870d3bb Mon Sep 17 00:00:00 2001 From: freya0926 Date: Tue, 21 Jul 2026 16:34:47 +0900 Subject: [PATCH] fix(qdrant): actually clear points on reset() for local Qdrant (#6412) Co-authored-by: freya0926 <299410795+freya0926@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 Co-authored-by: kartik-mem0 --- mem0/vector_stores/qdrant.py | 8 ++++++++ tests/vector_stores/test_qdrant.py | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/mem0/vector_stores/qdrant.py b/mem0/vector_stores/qdrant.py index 99cca10d1..b48e03c91 100644 --- a/mem0/vector_stores/qdrant.py +++ b/mem0/vector_stores/qdrant.py @@ -596,3 +596,11 @@ class Qdrant(VectorStoreBase): logger.warning(f"Resetting index {self.collection_name}...") self.delete_col() self.create_col(self.embedding_model_dims, self.on_disk) + if self.is_local: + # Local delete_collection() rmtree's with ignore_errors=True and leaves its + # sqlite handle open, so where an open file blocks unlink (Windows, NFS) the + # recreated collection re-adopts the old storage.sqlite. Drop what survived. + self.client.delete( + collection_name=self.collection_name, + points_selector=models.FilterSelector(filter=models.Filter(must=[])), + ) diff --git a/tests/vector_stores/test_qdrant.py b/tests/vector_stores/test_qdrant.py index d647abf6c..ac45026f5 100644 --- a/tests/vector_stores/test_qdrant.py +++ b/tests/vector_stores/test_qdrant.py @@ -54,6 +54,30 @@ class TestQdrant(unittest.TestCase): ) self.assertTrue(os.path.isfile(sentinel)) + def test_reset_clears_points_on_local_qdrant(self): + """#6411: reset() must drop points even when the collection dir survives delete_col().""" + with tempfile.TemporaryDirectory() as tmp: + store = Qdrant(collection_name="reset_me", embedding_model_dims=4, path=os.path.join(tmp, "qdrant")) + try: + self.assertTrue(store.is_local) + store.insert( + vectors=[[0.1, 0.2, 0.3, 0.4]], + payloads=[{"data": "remember me"}], + ids=[str(uuid.uuid4())], + ) + self.assertEqual(len(store.list(top_k=10)[0]), 1) + + # Simulate Windows/NFS, where rmtree(ignore_errors=True) silently fails + # on the open sqlite handle and the collection dir survives delete_col(). + with patch("qdrant_client.local.qdrant_local.shutil.rmtree"): + store.reset() + + self.assertEqual(len(store.list(top_k=10)[0]), 0) + sparse = store.client.get_collection("reset_me").config.params.sparse_vectors + self.assertIn("bm25", sparse or {}) + finally: + store.client.close() + def test_create_col(self): self.client_mock.get_collections.return_value = MagicMock(collections=[])