Repository navigation
Description
Summary
codebase-memory-mcp v0.8.1 (and earlier) contains a deleting corrupt db code
path that silently unlinks the project database file when its startup
integrity check raises any anomaly. This is a "delete on first suspicion"
design that causes total data loss with no backup, no log warning, and no
recovery path — even when the "corruption" is a false positive.
Evidence
The behavior is in the compiled binary and observable via strings:
deleting corrupt db
ERROR store.corrupt table=projects rows=%d (expected 1)
ERROR store.corrupt table=projects bad_root_path=%s
integrity_check_failed
malformed database schema (%s)
file is not a database
broke stale lock on %s
Related binary paths (WAL mode + atomic rename used for normal writes):
PRAGMA journal_mode = WAL;
%s.tmp
dump: rename failed
rename_to_cache
Trigger conditions (false positives)
In my case the project DB was deleted after I performed a sequence of
pkill -9 on the cbm process and binary swaps between standard and ui
variants (the install.sh --ui switch). The next cbm startup detected
"corruption" and deleted the 28 MB <project>.db file. Other plausible
triggers I can think of:
- WAL file leftover from a previously-SIGKILL'd cbm (most likely in
my case). When the old process is killed, SQLite's-waland-shm
sidecar files can be left in a state the new process interprets as
corruption. - Binary version drift between cbm builds (e.g., switching between
codebase-memory-mcp-darwin-arm64.tar.gzand
codebase-memory-mcp-ui-darwin-arm64.tar.gz). Even minor schema-version
differences would trip the check. - Lock-file contention — the
broke stale lock on %sstring shows cbm
forcibly breaks stale locks; the DB state immediately after lock break
may look anomalous and trigger the delete.
Repro
codebase-memory-mcp cli index_repository '{"repo_path":"/path/to/proj","mode":"full"}'pkill -9 -f "codebase-memory-mcp"while index is in progress (or
between operations)- Start cbm again. The
<proj>.dbfile disappears. - No log line other than
level=info msg=mem.init ...precedes the loss.
Impact
- Total data loss of the indexed project (in my case: 8 740 nodes /
26 412 edges / 28 MB SQLite, plus thegraph.db.zstartifact) - No backup, no
.corrupt.<timestamp>rename, no in-process log warning - User has no idea what happened until they re-open the UI and see
"No indexed projects" - Recovery requires re-running the full reindex, which costs time
(3-4 min for Linux kernel per the README, several minutes for any
real codebase)
Suggested fix
Replace the unlink with a rename to a timestamped .corrupt file and
emit a prominent stderr log so the user has a chance to act:
// pseudocode for the recovery branch
if (integrity_check_fails) {
char corrupt_path[PATH_MAX];
snprintf(corrupt_path, sizeof(corrupt_path),
"%s.corrupt.%ld", db_path, (long)time(NULL));
rename(db_path, corrupt_path);
fprintf(stderr,
"ERROR project database marked corrupt: %s\n"
"ERROR preserved as: %s\n"
"ERROR re-index: codebase-memory-mcp cli index_repository "
"'{\"repo_path\":\"...\",\"mode\":\"full\"}'\n",
db_path, corrupt_path);
}This preserves the evidence, lets the user inspect what was wrong, and
gives them a recovery path (file a bug with the corrupt DB attached).
Environment
- cbm 0.8.1 (binary
--versionandserverInfo.versionboth report 0.8.1;
note: prior 0.6.1 release had aserverInfo.version: 0.10.0mismatch
per issue #350) - macOS 26.4.1, Darwin 25.4.0 arm64, Apple Silicon
- Binary:
Mach-O 64-bit executable arm64, 270.9 MB (UI variant) - Related: issue #350
(UI HTTP server doesn't bind, closed) and
issue #402
(UI binary crashes mid-render, open) — both UI-related
Activity
DeusData commentedon Jun 23, 2026
Thanks for the detailed write-up and the
strings-level evidence — a delete-on-first-suspicion path with no backup and no recovery is not acceptable behavior, and I'm treating this as a data-loss bug (bug/stability/performance).Your WAL /
-shm-leftover-after-SIGKILLtheory is the most likely trigger; a schema-version mismatch from swapping between thestandardanduiarchives is also plausible. The fix direction here is to quarantine (rename the file aside) rather thanunlinkon a corruption signal, attempt WAL recovery first, and always log loudly before touching the file.Tracking this alongside the silent-corruption work in #391. If you still have the shell history around the deletion, the exact sequence would help me reproduce it.
jonlimx commentedon Jun 25, 2026
I checked
~/.zsh_history(8051 entries, persisted by oh-my-zsh). The exactpkill -9 cbmandinstall.sh --uisequence is not there — the onlypkillin my history issudo pkill -f qemu(unrelated), and the only cbm-related entries are wrapper commands I wrote (cbm-ui,cbm-ui-stop,cbm-status,cbm-info,cbm-full).The actual deletion sequence almost certainly ran through opencode's
bashtool, which spawns ephemeral shells that do not write to~/.zsh_history. So the "Repro" steps in the original report are a hypothesis (observed symptom + plausible cause), not a verified shell trace. Sorry for not flagging this when I filed the issue — I should have marked those steps as "best guess" rather than "repro".The most likely trigger is still the WAL/SHM-leftover theory: a
pkill -9of cbm mid-write leaves-wal/-shmsidecars that the next startup interprets as corruption. If you want a deterministic repro, the test case is probably:For PR #620: I'm happy to test the rename-on-corruption behavior once it lands. I have the v0.8.1 UI binary and a clean test repo I can use to reproduce the WAL-leftover path end-to-end.
yasku commentedon Jun 25, 2026
For sure! Let me know what u found as i got the same issue ... Right now it works clean, all testes passes but check it
yasku commentedon Jun 25, 2026
Fully tested locally on MacOS tahoe 26. Gates pass ok, pr check pass okey. Hope it helps
test(repro): data-loss + watcher reproductions for #557, #520
fix(mcp): back up corrupt DB instead of silently deleting it (#557)
DeusData commentedon Jun 28, 2026
Reproduced in the cumulative bug-reproduction suite in #667 and fixed there: on a "corrupt" detection the project DB is now backed up instead of being silently deleted, so a false-positive corruption check can no longer destroy a user's index. The reproduction stays as a regression guard.
(Lands when #667 merges.)
DeusData commentedon Sep 19, 2026
Thank you for the report and for clarifying which trigger details were hypotheses. The destructive recovery path was changed in 639bac9 and subsequently hardened in 0e00ef5; both are included in v0.11.0. Current recovery publishes a verified recovery snapshot before removing the live database, and preserves the live generation if backup preparation fails. Closing the silent-deletion defect as fixed. This does not claim that every possible corruption trigger has been eliminated.