Skip to content

fix: make corrupt-cache recovery say so instead of swallowing it - #342

Open
ProfSynapse wants to merge 2 commits into
mainfrom
fix/209-loud-cache-recovery
Open

fix: make corrupt-cache recovery say so instead of swallowing it#342
ProfSynapse wants to merge 2 commits into
mainfrom
fix/209-loud-cache-recovery

Conversation

@ProfSynapse

Copy link
Copy Markdown
Owner

Follow-up to #209.

Why

SQLitePersistenceService swallowed the integrity-check failure in a bare catch {}. The database was quietly rebuilt and the user saw only downstream symptoms — repeated waitForQueryReady timeouts, embeddings skipped, tool calls hanging.

That silence is why #209 went undiagnosed for months. The recovery worked; nobody could tell it had happened.

What changed

A new reportCacheRebuild logs at console.error, naming:

  • that the integrity check failed
  • the raw integrity_check output, or the thrown cause
  • that no data is lost, because the cache is replayed from the JSONL event store

console.error rather than the logger on purpose: logger.systemWarn and systemLog are no-ops in this build, so routing through them would have re-hidden the thing this PR exists to surface.

The outer read/deserialize catch routes through the same reporter, and the blobStore.remove() bare catch now warns.

The recovery logic itself is untouched. This only stops it being invisible.

Tests

Four, all failing pre-fix — three because nothing is logged at all, and one because the single existing line mentioned neither the rebuild nor the event store.

Not done

No live proof: reproducing it means deliberately corrupting the running vault's SQLite blob, and this branch didn't own the instance. The mechanism was reproduced during triage though — a 22.4 MB blob with a valid header and garbage pages, recovered on restart with all 803 conversations intact.

No Notice was added. console.error matches the file's convention, and the brief was to stop hiding the event, not to add UI. A user-facing notice is a reasonable follow-up if you want one.

🤖 Generated with Claude Code

https://claude.ai/code/session_01C6aSoCAS5gNoew6n9qv6DJ


Generated by Claude Code

claude added 2 commits August 14, 2026 19:43
`SQLitePersistenceService.loadDatabase` handled a failed integrity check in a
bare `catch {}`. The cache was discarded and rebuilt correctly, but nothing was
written to the console — so the only thing a user ever saw was the downstream
symptom (an empty or half-populated view) with no line tying it back to a
corrupt database. That is why #209 was undiagnosable from the reporter's
console for months.

Report it at console.error, which is where a user can actually find it, and say
all three things that matter: that the integrity check failed, the sqlite
`integrity_check` output or thrown cause behind it, and that no data is lost
because the cache is a rebuildable index replayed from the JSONL event store.
The outer read/deserialize failure now goes through the same reporter, so both
recovery paths explain themselves. The blob-delete failure inside
`recreateCorruptedDatabase` warns rather than vanishing — a remove that keeps
failing is the difference between corrupted once and corruption that can never
be cleared.

Recovery behaviour is unchanged; only its visibility is. All four new tests
fail against the pre-fix service (nothing is logged, or the log carries no
cause).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C6aSoCAS5gNoew6n9qv6DJ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants