Skip to content

Commit 6147321

Browse files
fix: Vector store persistence across server restarts (#3977)
# What does this PR do? This PR fixes a bug in LlamaStack 0.3.0 where vector stores created via the OpenAI-compatible API (`POST /v1/vector_stores`) would fail with `VectorStoreNotFoundError` after server restart when attempting operations like `vector_io.insert()` or `vector_io.query()`. The bug affected **6 vector IO providers**: `pgvector`, `sqlite_vec`, `chroma`, `milvus`, `qdrant`, and `weaviate`. Created with the assistance of: claude-4.5-sonnet ## Root Cause All affected providers had a broken `_get_and_cache_vector_store_index()` method that: 1. Did not load existing vector stores from persistent storage during initialization 2. Attempted to use `vector_store_table` (which was either `None` or a `KVStore` without the required `get_vector_store()` method) 3. Could not reload vector stores after server restart or cache miss ## Solution This PR implements a consistent pattern across all 6 providers: 1. **Load vector stores during initialization** - Pre-populate the cache from KV store on startup 2. **Fix lazy loading** - Modified `_get_and_cache_vector_store_index()` to load directly from KV store instead of relying on `vector_store_table` 3. **Remove broken dependency** - Eliminated reliance on the `vector_store_table` pattern ## Testing steps ### 1.1 Configure the stack Create or use an existing configuration with a vector IO provider. **Example `run.yaml`:** ```yaml vector_io_store: - provider_id: pgvector provider_type: remote::pgvector config: host: localhost port: 5432 db: llamastack user: llamastack password: llamastack inference: - provider_id: sentence-transformers provider_type: inline::sentence-transformers config: model: sentence-transformers/all-MiniLM-L6-v2 ``` ### 1.2 Start the server ```bash llama stack run run.yaml --port 5000 ``` Wait for the server to fully start. You should see: ``` INFO: Started server process INFO: Application startup complete ``` --- ## Step 2: Create a Vector Store ### 2.1 Create via API ```bash curl -X POST http://localhost:5000/v1/vector_stores \ -H "Content-Type: application/json" \ -d '{ "name": "test-persistence-store", "extra_body": { "embedding_model": "sentence-transformers/all-MiniLM-L6-v2", "embedding_dimension": 384, "provider_id": "pgvector" } }' | jq ``` ### 2.2 Expected Response ```json { "id": "vs_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "object": "vector_store", "name": "test-persistence-store", "status": "completed", "created_at": 1730304000, "file_counts": { "total": 0, "completed": 0, "in_progress": 0, "failed": 0, "cancelled": 0 }, "usage_bytes": 0 } ``` **Save the `id` field** (e.g., `vs_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d`) — you’ll need it for the next steps. --- ## Step 3: Insert Data (Before Restart) ### 3.1 Insert chunks into the vector store ```bash export VS_ID="vs_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" curl -X POST http://localhost:5000/vector-io/insert \ -H "Content-Type: application/json" \ -d "{ \"vector_store_id\": \"$VS_ID\", \"chunks\": [ { \"content\": \"Python is a high-level programming language known for its readability.\", \"metadata\": {\"source\": \"doc1\", \"page\": 1} }, { \"content\": \"Machine learning enables computers to learn from data without explicit programming.\", \"metadata\": {\"source\": \"doc2\", \"page\": 1} }, { \"content\": \"Neural networks are inspired by biological neurons in the brain.\", \"metadata\": {\"source\": \"doc3\", \"page\": 1} } ] }" ``` ### 3.2 Expected Response Status: **200 OK** Response: *Empty or success confirmation* --- ## Step 4: Query Data (Before Restart – Baseline) ### 4.1 Query the vector store ```bash curl -X POST http://localhost:5000/vector-io/query \ -H "Content-Type: application/json" \ -d "{ \"vector_store_id\": \"$VS_ID\", \"query\": \"What is machine learning?\" }" | jq ``` ### 4.2 Expected Response ```json { "chunks": [ { "content": "Machine learning enables computers to learn from data without explicit programming.", "metadata": {"source": "doc2", "page": 1} }, { "content": "Neural networks are inspired by biological neurons in the brain.", "metadata": {"source": "doc3", "page": 1} } ], "scores": [0.85, 0.72] } ``` **Checkpoint:** Works correctly before restart. --- ## Step 5: Restart the Server (Critical Test) ### 5.1 Stop the server In the terminal where it’s running: ``` Ctrl + C ``` Wait for: ``` Shutting down... ``` ### 5.2 Restart the server ```bash llama stack run run.yaml --port 5000 ``` Wait for: ``` INFO: Started server process INFO: Application startup complete ``` The vector store cache is now empty, but data should persist. --- ## Step 6: Verify Vector Store Exists (After Restart) ### 6.1 List vector stores ```bash curl http://localhost:5000/v1/vector_stores | jq ``` ### 6.2 Expected Response ```json { "object": "list", "data": [ { "id": "vs_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d", "name": "test-persistence-store", "status": "completed" } ] } ``` **Checkpoint:** Vector store should be listed. --- ## Step 7: Insert Data (After Restart – THE BUG TEST) ### 7.1 Insert new chunks ```bash curl -X POST http://localhost:5000/vector-io/insert \ -H "Content-Type: application/json" \ -d "{ \"vector_store_id\": \"$VS_ID\", \"chunks\": [ { \"content\": \"This chunk was inserted AFTER the server restart.\", \"metadata\": {\"source\": \"post-restart\", \"test\": true} } ] }" ``` ### 7.2 Expected Results **With Fix (Correct):** ``` Status: 200 OK Response: Success ``` **Without Fix (Bug):** ```json { "detail": "VectorStoreNotFoundError: Vector Store 'vs_a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d' not found." } ``` **Critical Test:** If insertion succeeds, the fix works. --- ## Step 8: Query Data (After Restart – Verification) ### 8.1 Query all data ```bash curl -X POST http://localhost:5000/vector-io/query \ -H "Content-Type: application/json" \ -d "{ \"vector_store_id\": \"$VS_ID\", \"query\": \"restart\" }" | jq ``` ### 8.2 Expected Response ```json { "chunks": [ { "content": "This chunk was inserted AFTER the server restart.", "metadata": {"source": "post-restart", "test": true} } ], "scores": [0.95] } ``` **Checkpoint:** Both old and new data are queryable. --- ## Step 9: Multiple Restart Test (Extra Verification) ### 9.1 Restart again ```bash Ctrl + C llama stack run run.yaml --port 5000 ``` ### 9.2 Query after restart ```bash curl -X POST http://localhost:5000/vector-io/query \ -H "Content-Type: application/json" \ -d "{ \"vector_store_id\": \"$VS_ID\", \"query\": \"programming\" }" | jq ``` **Expected:** Works correctly across multiple restarts. --------- Co-authored-by: Francisco Arceo <[email protected]>
1 parent 8f4c431 commit 6147321

File tree

8 files changed

+199
-29
lines changed

8 files changed

+199
-29
lines changed

src/llama_stack/providers/inline/vector_io/faiss/faiss.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ async def health(self) -> HealthResponse:
223223
return HealthResponse(status=HealthStatus.ERROR, message=f"Health check failed: {str(e)}")
224224

225225
async def register_vector_store(self, vector_store: VectorStore) -> None:
226-
assert self.kvstore is not None
226+
if self.kvstore is None:
227+
raise RuntimeError("KVStore not initialized. Call initialize() before registering vector stores.")
227228

228229
key = f"{VECTOR_DBS_PREFIX}{vector_store.identifier}"
229230
await self.kvstore.set(key=key, value=vector_store.model_dump_json())
@@ -239,7 +240,8 @@ async def list_vector_stores(self) -> list[VectorStore]:
239240
return [i.vector_store for i in self.cache.values()]
240241

241242
async def unregister_vector_store(self, vector_store_id: str) -> None:
242-
assert self.kvstore is not None
243+
if self.kvstore is None:
244+
raise RuntimeError("KVStore not initialized. Call initialize() before unregistering vector stores.")
243245

244246
if vector_store_id not in self.cache:
245247
return
@@ -248,6 +250,27 @@ async def unregister_vector_store(self, vector_store_id: str) -> None:
248250
del self.cache[vector_store_id]
249251
await self.kvstore.delete(f"{VECTOR_DBS_PREFIX}{vector_store_id}")
250252

253+
async def _get_and_cache_vector_store_index(self, vector_store_id: str) -> VectorStoreWithIndex | None:
254+
if vector_store_id in self.cache:
255+
return self.cache[vector_store_id]
256+
257+
if self.kvstore is None:
258+
raise RuntimeError("KVStore not initialized. Call initialize() before using vector stores.")
259+
260+
key = f"{VECTOR_DBS_PREFIX}{vector_store_id}"
261+
vector_store_data = await self.kvstore.get(key)
262+
if not vector_store_data:
263+
raise VectorStoreNotFoundError(vector_store_id)
264+
265+
vector_store = VectorStore.model_validate_json(vector_store_data)
266+
index = VectorStoreWithIndex(
267+
vector_store=vector_store,
268+
index=await FaissIndex.create(vector_store.embedding_dimension, self.kvstore, vector_store.identifier),
269+
inference_api=self.inference_api,
270+
)
271+
self.cache[vector_store_id] = index
272+
return index
273+
251274
async def insert_chunks(self, vector_store_id: str, chunks: list[Chunk], ttl_seconds: int | None = None) -> None:
252275
index = self.cache.get(vector_store_id)
253276
if index is None:

src/llama_stack/providers/inline/vector_io/sqlite_vec/sqlite_vec.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,14 @@ async def list_vector_stores(self) -> list[VectorStore]:
412412
return [v.vector_store for v in self.cache.values()]
413413

414414
async def register_vector_store(self, vector_store: VectorStore) -> None:
415+
if self.kvstore is None:
416+
raise RuntimeError("KVStore not initialized. Call initialize() before registering vector stores.")
417+
418+
# Save to kvstore for persistence
419+
key = f"{VECTOR_DBS_PREFIX}{vector_store.identifier}"
420+
await self.kvstore.set(key=key, value=vector_store.model_dump_json())
421+
422+
# Create and cache the index
415423
index = await SQLiteVecIndex.create(
416424
vector_store.embedding_dimension, self.config.db_path, vector_store.identifier
417425
)
@@ -421,13 +429,16 @@ async def _get_and_cache_vector_store_index(self, vector_store_id: str) -> Vecto
421429
if vector_store_id in self.cache:
422430
return self.cache[vector_store_id]
423431

424-
if self.vector_store_table is None:
425-
raise VectorStoreNotFoundError(vector_store_id)
432+
# Try to load from kvstore
433+
if self.kvstore is None:
434+
raise RuntimeError("KVStore not initialized. Call initialize() before using vector stores.")
426435

427-
vector_store = self.vector_store_table.get_vector_store(vector_store_id)
428-
if not vector_store:
436+
key = f"{VECTOR_DBS_PREFIX}{vector_store_id}"
437+
vector_store_data = await self.kvstore.get(key)
438+
if not vector_store_data:
429439
raise VectorStoreNotFoundError(vector_store_id)
430440

441+
vector_store = VectorStore.model_validate_json(vector_store_data)
431442
index = VectorStoreWithIndex(
432443
vector_store=vector_store,
433444
index=SQLiteVecIndex(

src/llama_stack/providers/remote/vector_io/chroma/chroma.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ def __init__(
131131

132132
async def initialize(self) -> None:
133133
self.kvstore = await kvstore_impl(self.config.persistence)
134-
self.vector_store_table = self.kvstore
135134

136135
if isinstance(self.config, RemoteChromaVectorIOConfig):
137136
log.info(f"Connecting to Chroma server at: {self.config.url}")
@@ -190,9 +189,16 @@ async def _get_and_cache_vector_store_index(self, vector_store_id: str) -> Vecto
190189
if vector_store_id in self.cache:
191190
return self.cache[vector_store_id]
192191

193-
vector_store = await self.vector_store_table.get_vector_store(vector_store_id)
194-
if not vector_store:
192+
# Try to load from kvstore
193+
if self.kvstore is None:
194+
raise RuntimeError("KVStore not initialized. Call initialize() before using vector stores.")
195+
196+
key = f"{VECTOR_DBS_PREFIX}{vector_store_id}"
197+
vector_store_data = await self.kvstore.get(key)
198+
if not vector_store_data:
195199
raise ValueError(f"Vector DB {vector_store_id} not found in Llama Stack")
200+
201+
vector_store = VectorStore.model_validate_json(vector_store_data)
196202
collection = await maybe_await(self.client.get_collection(vector_store_id))
197203
if not collection:
198204
raise ValueError(f"Vector DB {vector_store_id} not found in Chroma")

src/llama_stack/providers/remote/vector_io/milvus/milvus.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,16 @@ async def _get_and_cache_vector_store_index(self, vector_store_id: str) -> Vecto
328328
if vector_store_id in self.cache:
329329
return self.cache[vector_store_id]
330330

331-
if self.vector_store_table is None:
332-
raise VectorStoreNotFoundError(vector_store_id)
331+
# Try to load from kvstore
332+
if self.kvstore is None:
333+
raise RuntimeError("KVStore not initialized. Call initialize() before using vector stores.")
333334

334-
vector_store = await self.vector_store_table.get_vector_store(vector_store_id)
335-
if not vector_store:
335+
key = f"{VECTOR_DBS_PREFIX}{vector_store_id}"
336+
vector_store_data = await self.kvstore.get(key)
337+
if not vector_store_data:
336338
raise VectorStoreNotFoundError(vector_store_id)
337339

340+
vector_store = VectorStore.model_validate_json(vector_store_data)
338341
index = VectorStoreWithIndex(
339342
vector_store=vector_store,
340343
index=MilvusIndex(client=self.client, collection_name=vector_store.identifier, kvstore=self.kvstore),

src/llama_stack/providers/remote/vector_io/pgvector/pgvector.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,22 @@ async def initialize(self) -> None:
368368
log.exception("Could not connect to PGVector database server")
369369
raise RuntimeError("Could not connect to PGVector database server") from e
370370

371+
# Load existing vector stores from KV store into cache
372+
start_key = VECTOR_DBS_PREFIX
373+
end_key = f"{VECTOR_DBS_PREFIX}\xff"
374+
stored_vector_stores = await self.kvstore.values_in_range(start_key, end_key)
375+
for vector_store_data in stored_vector_stores:
376+
vector_store = VectorStore.model_validate_json(vector_store_data)
377+
pgvector_index = PGVectorIndex(
378+
vector_store=vector_store,
379+
dimension=vector_store.embedding_dimension,
380+
conn=self.conn,
381+
kvstore=self.kvstore,
382+
)
383+
await pgvector_index.initialize()
384+
index = VectorStoreWithIndex(vector_store, index=pgvector_index, inference_api=self.inference_api)
385+
self.cache[vector_store.identifier] = index
386+
371387
async def shutdown(self) -> None:
372388
if self.conn is not None:
373389
self.conn.close()
@@ -377,7 +393,13 @@ async def shutdown(self) -> None:
377393

378394
async def register_vector_store(self, vector_store: VectorStore) -> None:
379395
# Persist vector DB metadata in the KV store
380-
assert self.kvstore is not None
396+
if self.kvstore is None:
397+
raise RuntimeError("KVStore not initialized. Call initialize() before registering vector stores.")
398+
399+
# Save to kvstore for persistence
400+
key = f"{VECTOR_DBS_PREFIX}{vector_store.identifier}"
401+
await self.kvstore.set(key=key, value=vector_store.model_dump_json())
402+
381403
# Upsert model metadata in Postgres
382404
upsert_models(self.conn, [(vector_store.identifier, vector_store)])
383405

@@ -396,7 +418,8 @@ async def unregister_vector_store(self, vector_store_id: str) -> None:
396418
del self.cache[vector_store_id]
397419

398420
# Delete vector DB metadata from KV store
399-
assert self.kvstore is not None
421+
if self.kvstore is None:
422+
raise RuntimeError("KVStore not initialized. Call initialize() before unregistering vector stores.")
400423
await self.kvstore.delete(key=f"{VECTOR_DBS_PREFIX}{vector_store_id}")
401424

402425
async def insert_chunks(self, vector_store_id: str, chunks: list[Chunk], ttl_seconds: int | None = None) -> None:
@@ -413,13 +436,16 @@ async def _get_and_cache_vector_store_index(self, vector_store_id: str) -> Vecto
413436
if vector_store_id in self.cache:
414437
return self.cache[vector_store_id]
415438

416-
if self.vector_store_table is None:
417-
raise VectorStoreNotFoundError(vector_store_id)
439+
# Try to load from kvstore
440+
if self.kvstore is None:
441+
raise RuntimeError("KVStore not initialized. Call initialize() before using vector stores.")
418442

419-
vector_store = await self.vector_store_table.get_vector_store(vector_store_id)
420-
if not vector_store:
443+
key = f"{VECTOR_DBS_PREFIX}{vector_store_id}"
444+
vector_store_data = await self.kvstore.get(key)
445+
if not vector_store_data:
421446
raise VectorStoreNotFoundError(vector_store_id)
422447

448+
vector_store = VectorStore.model_validate_json(vector_store_data)
423449
index = PGVectorIndex(vector_store, vector_store.embedding_dimension, self.conn)
424450
await index.initialize()
425451
self.cache[vector_store_id] = VectorStoreWithIndex(vector_store, index, self.inference_api)

src/llama_stack/providers/remote/vector_io/qdrant/qdrant.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ async def shutdown(self) -> None:
183183
await super().shutdown()
184184

185185
async def register_vector_store(self, vector_store: VectorStore) -> None:
186-
assert self.kvstore is not None
186+
if self.kvstore is None:
187+
raise RuntimeError("KVStore not initialized. Call initialize() before registering vector stores.")
187188
key = f"{VECTOR_DBS_PREFIX}{vector_store.identifier}"
188189
await self.kvstore.set(key=key, value=vector_store.model_dump_json())
189190

@@ -200,20 +201,24 @@ async def unregister_vector_store(self, vector_store_id: str) -> None:
200201
await self.cache[vector_store_id].index.delete()
201202
del self.cache[vector_store_id]
202203

203-
assert self.kvstore is not None
204+
if self.kvstore is None:
205+
raise RuntimeError("KVStore not initialized. Call initialize() before using vector stores.")
204206
await self.kvstore.delete(f"{VECTOR_DBS_PREFIX}{vector_store_id}")
205207

206208
async def _get_and_cache_vector_store_index(self, vector_store_id: str) -> VectorStoreWithIndex | None:
207209
if vector_store_id in self.cache:
208210
return self.cache[vector_store_id]
209211

210-
if self.vector_store_table is None:
211-
raise ValueError(f"Vector DB not found {vector_store_id}")
212+
# Try to load from kvstore
213+
if self.kvstore is None:
214+
raise RuntimeError("KVStore not initialized. Call initialize() before using vector stores.")
212215

213-
vector_store = await self.vector_store_table.get_vector_store(vector_store_id)
214-
if not vector_store:
216+
key = f"{VECTOR_DBS_PREFIX}{vector_store_id}"
217+
vector_store_data = await self.kvstore.get(key)
218+
if not vector_store_data:
215219
raise VectorStoreNotFoundError(vector_store_id)
216220

221+
vector_store = VectorStore.model_validate_json(vector_store_data)
217222
index = VectorStoreWithIndex(
218223
vector_store=vector_store,
219224
index=QdrantIndex(client=self.client, collection_name=vector_store.identifier),

src/llama_stack/providers/remote/vector_io/weaviate/weaviate.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,13 +346,16 @@ async def _get_and_cache_vector_store_index(self, vector_store_id: str) -> Vecto
346346
if vector_store_id in self.cache:
347347
return self.cache[vector_store_id]
348348

349-
if self.vector_store_table is None:
350-
raise VectorStoreNotFoundError(vector_store_id)
349+
# Try to load from kvstore
350+
if self.kvstore is None:
351+
raise RuntimeError("KVStore not initialized. Call initialize() before using vector stores.")
351352

352-
vector_store = await self.vector_store_table.get_vector_store(vector_store_id)
353-
if not vector_store:
353+
key = f"{VECTOR_DBS_PREFIX}{vector_store_id}"
354+
vector_store_data = await self.kvstore.get(key)
355+
if not vector_store_data:
354356
raise VectorStoreNotFoundError(vector_store_id)
355357

358+
vector_store = VectorStore.model_validate_json(vector_store_data)
356359
client = self._get_client()
357360
sanitized_collection_name = sanitize_collection_name(vector_store.identifier, weaviate_format=True)
358361
if not client.collections.exists(sanitized_collection_name):

tests/unit/providers/vector_io/test_vector_io_openai_vector_stores.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,99 @@ async def test_persistence_across_adapter_restarts(vector_io_adapter):
9292
await vector_io_adapter.shutdown()
9393

9494

95+
async def test_vector_store_lazy_loading_from_kvstore(vector_io_adapter):
96+
"""
97+
Test that vector stores can be lazy-loaded from KV store when not in cache.
98+
99+
Verifies that clearing the cache doesn't break vector store access - they
100+
can be loaded on-demand from persistent storage.
101+
"""
102+
await vector_io_adapter.initialize()
103+
104+
vector_store_id = f"lazy_load_test_{np.random.randint(1e6)}"
105+
vector_store = VectorStore(
106+
identifier=vector_store_id,
107+
provider_id="test_provider",
108+
embedding_model="test_model",
109+
embedding_dimension=128,
110+
)
111+
await vector_io_adapter.register_vector_store(vector_store)
112+
assert vector_store_id in vector_io_adapter.cache
113+
114+
vector_io_adapter.cache.clear()
115+
assert vector_store_id not in vector_io_adapter.cache
116+
117+
loaded_index = await vector_io_adapter._get_and_cache_vector_store_index(vector_store_id)
118+
assert loaded_index is not None
119+
assert loaded_index.vector_store.identifier == vector_store_id
120+
assert vector_store_id in vector_io_adapter.cache
121+
122+
cached_index = await vector_io_adapter._get_and_cache_vector_store_index(vector_store_id)
123+
assert cached_index is loaded_index
124+
125+
await vector_io_adapter.shutdown()
126+
127+
128+
async def test_vector_store_preloading_on_initialization(vector_io_adapter):
129+
"""
130+
Test that vector stores are preloaded from KV store during initialization.
131+
132+
Verifies that after restart, all vector stores are automatically loaded into
133+
cache and immediately accessible without requiring lazy loading.
134+
"""
135+
await vector_io_adapter.initialize()
136+
137+
vector_store_ids = [f"preload_test_{i}_{np.random.randint(1e6)}" for i in range(3)]
138+
for vs_id in vector_store_ids:
139+
vector_store = VectorStore(
140+
identifier=vs_id,
141+
provider_id="test_provider",
142+
embedding_model="test_model",
143+
embedding_dimension=128,
144+
)
145+
await vector_io_adapter.register_vector_store(vector_store)
146+
147+
for vs_id in vector_store_ids:
148+
assert vs_id in vector_io_adapter.cache
149+
150+
await vector_io_adapter.shutdown()
151+
await vector_io_adapter.initialize()
152+
153+
for vs_id in vector_store_ids:
154+
assert vs_id in vector_io_adapter.cache
155+
156+
for vs_id in vector_store_ids:
157+
loaded_index = await vector_io_adapter._get_and_cache_vector_store_index(vs_id)
158+
assert loaded_index is not None
159+
assert loaded_index.vector_store.identifier == vs_id
160+
161+
await vector_io_adapter.shutdown()
162+
163+
164+
async def test_kvstore_none_raises_runtime_error(vector_io_adapter):
165+
"""
166+
Test that accessing vector stores with uninitialized kvstore raises RuntimeError.
167+
168+
Verifies proper RuntimeError is raised instead of assertions when kvstore is None.
169+
"""
170+
await vector_io_adapter.initialize()
171+
172+
vector_store_id = f"kvstore_none_test_{np.random.randint(1e6)}"
173+
vector_store = VectorStore(
174+
identifier=vector_store_id,
175+
provider_id="test_provider",
176+
embedding_model="test_model",
177+
embedding_dimension=128,
178+
)
179+
await vector_io_adapter.register_vector_store(vector_store)
180+
181+
vector_io_adapter.cache.clear()
182+
vector_io_adapter.kvstore = None
183+
184+
with pytest.raises(RuntimeError, match="KVStore not initialized"):
185+
await vector_io_adapter._get_and_cache_vector_store_index(vector_store_id)
186+
187+
95188
async def test_register_and_unregister_vector_store(vector_io_adapter):
96189
unique_id = f"foo_db_{np.random.randint(1e6)}"
97190
dummy = VectorStore(

0 commit comments

Comments
 (0)