Skip to content

fix(backends/chroma): release SQLite file lock on close_palace/close (#1067)#1105

Merged
igorls merged 1 commit intoMemPalace:developfrom
mvalentsev:fix/chroma-backend-close-releases-lock
May 6, 2026
Merged

fix(backends/chroma): release SQLite file lock on close_palace/close (#1067)#1105
igorls merged 1 commit intoMemPalace:developfrom
mvalentsev:fix/chroma-backend-close-releases-lock

Conversation

@mvalentsev
Copy link
Copy Markdown
Contributor

@mvalentsev mvalentsev commented Apr 22, 2026

Problem

ChromaBackend.close_palace() and close() evict cached PersistentClients from self._clients without calling client.close(). chromadb 1.5.x retains the rust-side SQLite file lock until GC, so reopening the same palace path after shutil.rmtree + re-create within one process fails:

chromadb.errors.InternalError: Query error: Database error:
error returned from database: (code: 1032) attempt to write a readonly database

SQLite code 1032 is SQLITE_READONLY_DBMOVED. Reported and diagnosed in #1067.

Fix

_close_client() helper calls PersistentClient.close() with a try/except fallback for older chromadb that does not expose it. Three sites route through it:

  • close_palace(palace): explicit per-palace teardown
  • close(): whole-backend shutdown, iterates cached clients before clearing
  • _client() invalidation on missing chroma.sqlite3: palace rebuilt under us

The _client() auto-invalidation branch on mtime/inode change is left alone. Callers there may still hold a live ChromaCollection backed by the outgoing client; closing it would clear the rust bindings mid-use.

Test plan

  • test_chroma_close_palace_releases_sqlite_lock_for_reopen: close, rmtree, reopen same path
  • test_chroma_close_releases_all_cached_clients: two palaces, whole-backend close, each reopenable
  • Both new tests fail on current develop with SQLite code 1032 and pass with the fix
  • Repro from the issue body runs to completion after the fix

Credits @xelauvas for the diagnosis and proposed direction.

Fixes #1067.

@mvalentsev mvalentsev marked this pull request as ready for review April 22, 2026 11:05
@mvalentsev mvalentsev force-pushed the fix/chroma-backend-close-releases-lock branch from c8a6938 to 195eed2 Compare April 22, 2026 11:10
@igorls igorls added bug Something isn't working storage labels Apr 24, 2026
@mvalentsev mvalentsev force-pushed the fix/chroma-backend-close-releases-lock branch from 195eed2 to 4260706 Compare April 26, 2026 18:59
@igorls igorls added this to the v3.3.5 milestone May 2, 2026
…emPalace#1067)

ChromaBackend.close_palace() and close() evicted cached PersistentClients
from self._clients without calling client.close(), so chromadb 1.5.x kept
the rust-side SQLite file lock until GC. Reopening the same palace path
after shutil.rmtree + re-create within one process then failed with
SQLITE_READONLY_DBMOVED (SQLite code 1032).

Add _close_client() helper with a try/except fallback for older chromadb,
and route close_palace(), close(), and the DB-file-missing invalidation
branch of _client() through it. The mtime/inode auto-invalidation branch
is left as-is: callers there may still hold a live ChromaCollection
handle, and closing out from under them clears the rust bindings mid-use.

Regression tests cover close_palace reopen-same-path and whole-backend
close for multiple palaces.
@mvalentsev mvalentsev force-pushed the fix/chroma-backend-close-releases-lock branch 2 times, most recently from d5a5daf to 45df1a2 Compare May 3, 2026 14:23
@igorls igorls merged commit ef0e45a into MemPalace:develop May 6, 2026
6 checks passed
igorls added a commit that referenced this pull request May 6, 2026
…1282 #1167 #1160

Bundled CHANGELOG entries for the seven Tier-1 PRs merged today, including
the behavior-change call-out for #1167 (KG date validators now reject
non-ISO inputs that previously produced silent empty results).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working storage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ChromaBackend._clients.pop() does not close() underlying PersistentClient; causes SQLITE_READONLY_DBMOVED on reopen

2 participants