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
With auto_index = true, the background watcher periodically re-indexes watched projects. Each write of the persisted graph DB leaves behind a full-size .db.stage.<random> temporary file, and in at least one case a nested.db.stage.<A>.stage.<B> copy was also created. For a large repo these temp files are ~1.1 GB each, so a few re-index cycles silently fill the system disk. The temp files are never reclaimed even after a subsequent re-index succeeds and commits a fresh X.db.
This looks like a variant of the re-index write-amplification family (#1083 WAL unbounded, #937 watcher re-index write amplification, #897/#1016 stale WAL/SHM sidecars), but the specific orphaned .db.stage.* temp files (including nested staging) does not appear to have a dedicated report.
Orphaned temp, older than the committed DB. The committed X.db has mtime 00:32, but the .stage.mjQU5l temp has mtime 00:17. So a later re-index committed a fresh X.db, yet the earlier 00:17.stage copy (and its nested copy) were never deleted — pure leak.
Nested staging.X.db.stage.mjQU5l.stage.VgdLsO (+ -shm/-wal) means the writer staged its own temp file a second time. This indicates the atomic "write temp → rename" path is itself being re-staged during a re-index, multiplying the on-disk footprint (here: 1.1 GB × 3 copies ≈ 3.3 GB for one project).
No live handle.lsof shows no process currently holds these .stage.* files, so they are safe to delete — they are leftovers, not in-flight writes.
Smaller watched repos do not carry leftover .stage.* files, consistent with the leak scaling with graph size × re-index frequency.
logs/cbm-daemon.log shows the watcher firing watcher.changed repeatedly (strategy=git) for the watched projects.
Suspected mechanism
The persisted graph DB is written atomically: <project>.db.stage.<random> is written, then renamed over <project>.db. With auto_index on, the watcher re-indexes on every git/file change. When re-indexes overlap or a later write lands before an earlier temp is cleaned up, the temp (and worse, a nested temp-of-temp) is left behind and never reclaimed. Because each temp is a full copy of the ~1.1 GB graph, disk usage grows without bound across idle re-index cycles.
Silent: no log warning, no auto-cleanup of orphaned stages.
Suggested fixes
On commit/rename, unlink any pre-existing <project>.db.stage.* in the cache root (and never let the staging glob match *.stage.* inputs, to prevent nested temp-of-temp re-staging).
Optionally VACUUM INTO / compact and write directly to a single temp name with a guaranteed unlink on both success and failure paths.
Steps to reproduce
codebase-memory-mcp config set auto_index true
Index a large repo (graph DB ≥ 1 GB) and leave it watched.
Let the watcher trigger several re-indexes (or make file/git changes under the repo).
Inspect the cache root — orphaned *.db.stage.<random> files accumulate; under overlap a nested *.db.stage.<A>.stage.<B> appears.
Note on diagnostics
The README asks for logs/trajectory.ndjson, but no trajectory.ndjson / snapshot.json is present in this cache root (likely rotated/absent in 0.10.8 local layout). The file-system evidence above is from the live cache at report time and reproduces the leak deterministically.
Summary
With
auto_index = true, the background watcher periodically re-indexes watched projects. Each write of the persisted graph DB leaves behind a full-size.db.stage.<random>temporary file, and in at least one case a nested.db.stage.<A>.stage.<B>copy was also created. For a large repo these temp files are ~1.1 GB each, so a few re-index cycles silently fill the system disk. The temp files are never reclaimed even after a subsequent re-index succeeds and commits a freshX.db.This looks like a variant of the re-index write-amplification family (#1083 WAL unbounded, #937 watcher re-index write amplification, #897/#1016 stale WAL/SHM sidecars), but the specific orphaned
.db.stage.*temp files (including nested staging) does not appear to have a dedicated report.Environment
CBM_CACHE_DIR/ cache root:~/.cache/codebase-memory-mcpauto_index = true(single key/value in_config.db)<VOLUME>-<PROJECT>— a large private repo whose persisted graph DB is ~1.1 GB (names redacted for privacy)Evidence (current cache root — repo-identifying names redacted)
Observations:
X.dbhas mtime00:32, but the.stage.mjQU5ltemp has mtime00:17. So a later re-index committed a freshX.db, yet the earlier00:17.stagecopy (and its nested copy) were never deleted — pure leak.X.db.stage.mjQU5l.stage.VgdLsO(+-shm/-wal) means the writer staged its own temp file a second time. This indicates the atomic "write temp → rename" path is itself being re-staged during a re-index, multiplying the on-disk footprint (here: 1.1 GB × 3 copies ≈ 3.3 GB for one project).lsofshows no process currently holds these.stage.*files, so they are safe to delete — they are leftovers, not in-flight writes..stage.*files, consistent with the leak scaling with graph size × re-index frequency.logs/cbm-daemon.logshows the watcher firingwatcher.changedrepeatedly (strategy=git) for the watched projects.Suspected mechanism
The persisted graph DB is written atomically:
<project>.db.stage.<random>is written, then renamed over<project>.db. Withauto_indexon, the watcher re-indexes on every git/file change. When re-indexes overlap or a later write lands before an earlier temp is cleaned up, the temp (and worse, a nestedtemp-of-temp) is left behind and never reclaimed. Because each temp is a full copy of the ~1.1 GB graph, disk usage grows without bound across idle re-index cycles.Impact
Suggested fixes
<project>.db.stage.*in the cache root (and never let the staging glob match*.stage.*inputs, to prevent nestedtemp-of-tempre-staging).VACUUM INTO/ compact and write directly to a single temp name with a guaranteedunlinkon both success and failure paths.Steps to reproduce
codebase-memory-mcp config set auto_index true*.db.stage.<random>files accumulate; under overlap a nested*.db.stage.<A>.stage.<B>appears.Note on diagnostics
The README asks for
logs/trajectory.ndjson, but notrajectory.ndjson/snapshot.jsonis present in this cache root (likely rotated/absent in 0.10.8 local layout). The file-system evidence above is from the live cache at report time and reproduces the leak deterministically.Related: #1083, #937, #897, #1016, #1204, #1828