claude-memory/graph/fixes/fix-race-condition-in-cognitive-memory-save-state-loses-last-59268a.md
2026-02-20 00:47:17 -06:00

1.7 KiB

id type title tags importance confidence created updated relations
59268a95-4712-48b4-bccb-6171c7885301 fix Fix: Race condition in cognitive-memory _save_state loses last_reflection timestamp when daily+weekly timers collide
cognitive-memory
fix
race-condition
systemd
state-management
atomicity
0.8 0.8 2026-02-20T06:47:07.701221+00:00 2026-02-20T06:47:17.701728+00:00
target type direction strength edge_id
b33e2316-6313-4ed9-b95a-3a469b820101 CAUSES outgoing 0.9 6f7d12e4-b494-4aea-9be9-f43a5492719c

Race Condition in _save_state Corrupts last_reflection Timestamp

Symptom

REFLECTION.md showed "Last reflection: never" despite the weekly reflect timer having run successfully.

Root Cause

Two concurrent issues:

  1. Timer collision: The daily timer (decay) and weekly timer (reflect) could fire simultaneously. OnCalendar=weekly resolves to Mon midnight, which overlaps with OnCalendar=daily on Mondays. Both processes load and save _state.json concurrently.

  2. Non-atomic writes with silent failure: _save_state() would overwrite _state.json without first merging existing state, so decay's write could clobber the last_reflection key written by reflect. Additionally, _load_state() silently caught JSONDecodeError and returned an empty default dict, permanently losing the key on any write collision.

Fix

  1. _save_state() now merges with existing on-disk state before writing (read-modify-write pattern).
  2. Writes use atomic tempfile + os.replace() to prevent partial writes.
  3. Weekly timer changed from OnCalendar=weekly to OnCalendar=Sun *-*-* 02:00:00 to avoid midnight collision with the daily timer.

Commit

Commit 7f120f8 in the cognitive-memory repo.