#11860: fix(memory): enable SQLite WAL mode for concurrent access safety
agents
stale
Cluster:
QMD Memory Management Fixes
## Problem
The memory SQLite database can experience corruption or SQLITE_BUSY errors when multiple processes access it concurrently — specifically when file-watcher, session-delta sync, and batch memory sync run simultaneously. This was observed in production with heartbeat-triggered memory indexing coinciding with cron job writes.
## Solution
Enable SQLite WAL (Write-Ahead Logging) journal mode on database open. WAL allows concurrent readers and a single writer without blocking, which is exactly the access pattern of the memory index (multiple read queries during agent turns + background write operations).
The change adds `PRAGMA journal_mode=WAL` in two places:
- `src/memory/manager.ts` — when opening the database connection
- `src/memory/memory-schema.ts` — during initial schema creation
## Additional fix
The `read` tool handler in `pi-embedded-subscribe.handlers.tools.ts` now accepts both `path` and `file_path` parameter names, matching the tool schema that advertises both.
## Testing
Tested in production over 48+ hours with 30-minute heartbeat intervals, concurrent cron jobs, and active sub-agent sessions. No SQLITE_BUSY errors or corruption since applying WAL mode.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR enables SQLite write-ahead logging (WAL) for the memory index by executing `PRAGMA journal_mode=WAL` when opening the DB connection (`src/memory/manager.ts`) and again during schema initialization (`src/memory/memory-schema.ts`). It also updates the embedded tool event handler to accept both `path` and `file_path` for the `read` tool (`src/agents/pi-embedded-subscribe.handlers.tools.ts`).
Overall this fits the memory subsystem’s access pattern (many reads + background writes) and should reduce `SQLITE_BUSY` issues, but the current implementation assumes WAL is successfully enabled without verifying the effective journal mode.
<h3>Confidence Score: 4/5</h3>
- This PR is likely safe to merge, but it may not fully fix the concurrency issue in environments where WAL cannot be enabled.
- Changes are small and localized, but WAL activation isn’t verified; if SQLite refuses WAL for the underlying filesystem/config, the code will continue as before and the original production issue can persist without visibility.
- src/memory/memory-schema.ts and src/memory/manager.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#16917: fix(memory): close stale SQLite connection after qmd update
by zerone0x · 2026-02-15
75.5%
#15620: fix(memory): await sync in search to prevent database closure race
by superlowburn · 2026-02-13
72.6%
#4386: fix(memory): persist dirty flag to prevent false positive on status
by Iamadig · 2026-01-30
72.3%
#8706: fix(memory): fall back to better-sqlite3 when node:sqlite lacks FTS5
by ElmerProject · 2026-02-04
72.3%
#10644: feat: add runDuringHeartbeats option for memory flush (AI Assisted)
by tripphillips · 2026-02-06
71.8%
#19179: fix(memory): respect readonly mode in database initialization
by marliechorgan · 2026-02-17
71.5%
#21217: fix: memory prune command to prevent unbounded MEMORY.md growth
by theognis1002 · 2026-02-19
71.2%
#14576: Fix/memory loss bugs
by ENCHIGO · 2026-02-12
71.0%
#9678: Cross-agent memory read allowlist
by Helmi · 2026-02-05
70.2%
#2884: fix: Create memory directory and symlink identity files during work...
by webdevtodayjason · 2026-01-27
70.1%