You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
vec0 module not loaded in worker connections (Windows) — embeddings reindex fails with "no such module: vec0" #767
basic-memory reindex -p <project> populates the knowledge graph (entities, relations, observations) but generates 0 embeddings. Status panel reports:
Indexed: 0/258
Status: Reindex recommended
Reason: SQLite vector tables exist but sqlite-vec is unavailable in this Python environment — install/update basic-memory, then run: bm reindex --embeddings
Running the suggested fix bm reindex -p vault --embeddings raises:
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such module: vec0
[SQL: DELETE FROM search_vector_embeddings WHERE rowid IN (SELECT id FROM search_vector_chunks WHERE project_id = ? AND entity_id NOT IN (SELECT id FROM entity WHERE project_id = ?))]
Diagnosis
sqlite-vec loads correctly in the same uvx environment when invoked directly:
So the package is installed and loadable. The bug appears to be that basic-memory's worker SQLAlchemy connections don't call enable_load_extension + sqlite_vec.load() before issuing queries that depend on the vec0 virtual table.
Suggested fix
Hook a connect event on the SQLAlchemy engine to enable extension loading and load sqlite_vec on each new connection, similar to:
basic-memory project default <name> is currently a no-op — returns "No default project is currently set" even after project add, and editing default_project directly in ~/.basic-memory/config.json gets reverted on the next CLI invocation.
Thanks for the detailed reports — and special thanks to @mrhoga for tracing the exact bypass path in search_service.py. That diagnosis was correct for v0.20.3.
Status on main
The specific code path you identified has already been refactored. In v0.20.3, _purge_stale_search_rows ran the embedding cleanup via self.repository.execute_query(...), which pulled a fresh connection from the SQLAlchemy pool with no vec0 loaded — exactly the failure mode you described.
On main, that branch was rewritten in PR #731 to delegate to a new method on the repository:
# SQLite vec has no CASCADE — must delete embeddings before chunksifisinstance(self.repository, SQLiteSearchRepository):
awaitself.repository.delete_stale_vector_rows()
else:
# Postgres CASCADE handles embedding deletion automaticallyawaitself.repository.execute_query(...)
And delete_stale_vector_rows opens its own session and loads sqlite-vec before issuing the DELETE — src/basic_memory/repository/sqlite_search_repository.py:591-619:
asyncdefdelete_stale_vector_rows(self) ->None:
awaitself._ensure_vector_tables()
asyncwithdb.scoped_session(self.session_maker) assession:
awaitself._ensure_sqlite_vec_loaded(session) # <-- the missing piece in 0.20.3
...
awaitsession.execute(
text("DELETE FROM search_vector_embeddings WHERE rowid IN (...)"),
params,
)
The wider invariant (every method that touches vec0 must load sqlite-vec on its own session) is now consistent across the repository — _ensure_sqlite_vec_loaded is called in delete_stale_vector_rows, _ensure_vector_tables, and the per-entity vector sync paths.
Suggested next step
Could you re-test against main (or wait for the next release after v0.20.3)? The existing integration test test_reindex_vectors (tests/services/test_search_service.py:1213) exercises the full reindex_vectors → _purge_stale_search_rows → delete_stale_vector_rows chain end-to-end with semantic enabled, which is what your reproduction hits.
If bm reindex --embeddings still fails for you on main, please reopen with the new traceback — the only ways the failure could survive that refactor are (a) a different vec0-touching SQL still routed through execute_query, or (b) _ensure_sqlite_vec_loaded failing silently on Windows. Both would be useful to see.
I'll close as fixed pending the next release. @andrewmautone — your "side note" about bm project default is a real separate issue; please do file it if you have a moment.
Activity
phernandez commentedon Apr 29, 2026
Thanks for the detailed reports — and special thanks to @mrhoga for tracing the exact bypass path in
search_service.py. That diagnosis was correct for v0.20.3.Status on
mainThe specific code path you identified has already been refactored. In v0.20.3,
_purge_stale_search_rowsran the embedding cleanup viaself.repository.execute_query(...), which pulled a fresh connection from the SQLAlchemy pool with no vec0 loaded — exactly the failure mode you described.On
main, that branch was rewritten in PR #731 to delegate to a new method on the repository:src/basic_memory/services/search_service.py:599-610(current main):And
delete_stale_vector_rowsopens its own session and loads sqlite-vec before issuing the DELETE —src/basic_memory/repository/sqlite_search_repository.py:591-619:The wider invariant (every method that touches
vec0must load sqlite-vec on its own session) is now consistent across the repository —_ensure_sqlite_vec_loadedis called indelete_stale_vector_rows,_ensure_vector_tables, and the per-entity vector sync paths.Suggested next step
Could you re-test against
main(or wait for the next release afterv0.20.3)? The existing integration testtest_reindex_vectors(tests/services/test_search_service.py:1213) exercises the fullreindex_vectors → _purge_stale_search_rows → delete_stale_vector_rowschain end-to-end with semantic enabled, which is what your reproduction hits.If
bm reindex --embeddingsstill fails for you onmain, please reopen with the new traceback — the only ways the failure could survive that refactor are (a) a different vec0-touching SQL still routed throughexecute_query, or (b)_ensure_sqlite_vec_loadedfailing silently on Windows. Both would be useful to see.I'll close as fixed pending the next release. @andrewmautone — your "side note" about
bm project defaultis a real separate issue; please do file it if you have a moment.phernandez commentedon Apr 29, 2026
Duplicate of #735 — same root cause, fixed on
main. Closing.