Version: codebase-memory-mcp 0.8.1 (built from source)
Platform: macOS (Apple Silicon) · Install channel: Built from source · Binary variant: standard
What happened, and what did you expect?
Three code paths install a brand-new DB file at a path where a previous DB generation lived, and none of them removes an existing <path>-wal / <path>-shm sidecar:
- the pipeline dump —
cbm_gbuf_dump_to_sqlite → the custom page writer opens the final cache path with fopen(path, "wb");
cbm_artifact_import — renames the imported file over the cache path (it cleans up the tmp file's sidecars, not the destination's);
cbm_store_dump_to_file — whose comment asserts the old sidecars "become stale and get recreated by the next reader".
That assertion is wrong: SQLite decides whether to replay a WAL purely from the sidecar's own header/checksums, not from any tie to the main file. A leftover WAL from a crashed or never-closed previous session is therefore recovered on top of the freshly installed file at the next open, splicing old-generation pages into it — short indexes, btreeInitPage failures, or silently resurrected stale rows depending on which frames land. The full pipeline path has no pre-dump sidecar cleanup at all (the incremental path happens to unlink them first, so the two pipelines disagree).
Expected: any code path that installs a fresh DB file deletes the destination's -wal/-shm first.
Reproduction
- Open a store at
<path>, insert a few hundred rows; while the connection is still open, copy the hot <path>-wal aside. Close cleanly (checkpoint removes the WAL).
- Restore the copied
-wal next to <path> — simulating a crashed session's leftover.
- Rebuild
<path> from scratch (re-index the project, or any of the three paths above).
- Open the DB: the stale WAL is replayed over the new file.
PRAGMA quick_check fails and/or row counts show the previous generation's data.
Cascade
An independent producer of the same corruption class as #895 (torn fast export); like it, the damage is then hidden by #896 (scans swallow SQLITE_CORRUPT). Fourth companion issue (malformed-JSON emission) linked in a comment once created.
Maintainer note
I have a working private fix for this (with reproduce-first regression tests) that I can submit as a PR. Before I do, I'd prefer you groom this issue — confirm the framing, tag, and prioritize — so the PR lands against an agreed shape.
Confirmations
Version: codebase-memory-mcp 0.8.1 (built from source)
Platform: macOS (Apple Silicon) · Install channel: Built from source · Binary variant: standard
What happened, and what did you expect?
Three code paths install a brand-new DB file at a path where a previous DB generation lived, and none of them removes an existing
<path>-wal/<path>-shmsidecar:cbm_gbuf_dump_to_sqlite→ the custom page writer opens the final cache path withfopen(path, "wb");cbm_artifact_import— renames the imported file over the cache path (it cleans up the tmp file's sidecars, not the destination's);cbm_store_dump_to_file— whose comment asserts the old sidecars "become stale and get recreated by the next reader".That assertion is wrong: SQLite decides whether to replay a WAL purely from the sidecar's own header/checksums, not from any tie to the main file. A leftover WAL from a crashed or never-closed previous session is therefore recovered on top of the freshly installed file at the next open, splicing old-generation pages into it — short indexes,
btreeInitPagefailures, or silently resurrected stale rows depending on which frames land. The full pipeline path has no pre-dump sidecar cleanup at all (the incremental path happens to unlink them first, so the two pipelines disagree).Expected: any code path that installs a fresh DB file deletes the destination's
-wal/-shmfirst.Reproduction
<path>, insert a few hundred rows; while the connection is still open, copy the hot<path>-walaside. Close cleanly (checkpoint removes the WAL).-walnext to<path>— simulating a crashed session's leftover.<path>from scratch (re-index the project, or any of the three paths above).PRAGMA quick_checkfails and/or row counts show the previous generation's data.Cascade
An independent producer of the same corruption class as #895 (torn fast export); like it, the damage is then hidden by #896 (scans swallow
SQLITE_CORRUPT). Fourth companion issue (malformed-JSON emission) linked in a comment once created.Maintainer note
I have a working private fix for this (with reproduce-first regression tests) that I can submit as a PR. Before I do, I'd prefer you groom this issue — confirm the framing, tag, and prioritize — so the PR lands against an agreed shape.
Confirmations