[BUG] Auto-memory instructions direct an immediate MEMORY.md pointer edit, but the read-before-write gate deterministically rejects it
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
The auto-memory system prompt and the Edit/Write read-before-write gate contradict each other, producing a deterministic error on the first memory save of essentially every session that saves one.
The memory instructions (a) inject MEMORY.md's full content into context every session, and (b) direct: "After writing the file, add a one-line pointer in MEMORY.md". The model follows them — saves the memory file, then immediately Edits MEMORY.md. The gate rejects with File has not been read yet. Read it first before writing to it, because no in-conversation Read of MEMORY.md has occurred (on a first save, none could reasonably have occurred — the file's content is already in the system prompt verbatim, so an explicit Read is redundant).
The recovery is always the same wasted loop: error → Read (a file already in context) → retry Edit → success. Several transcripts show 2–3 consecutive Reads during recovery. Measured over 14 days of local transcripts for one project (152 sessions): 106 File has not been read yet errors total, on every single day of the window, across client versions 2.1.197 → 2.1.209; the MEMORY.md-pointer flow is the reproducible core.
What Should Happen?
Any one of these resolves the contradiction:
- Files whose content the harness itself injects into context (
MEMORY.md, and arguably CLAUDE.md) count as read-satisfied for the Edit/Write gate. - The memory instructions say to Read
MEMORY.mdbefore adding the pointer line (documents the extra round-trip instead of guaranteeing an error). - Edit validates by content match (unique
old_stringfound ⇒ proceed) instead of requiring a prior Read — some current build already appears to behave this way (see Additional Information).
Error Messages/Logs
Representative sequence extracted from a session transcript (timestamps, tool, target):
05:46:18 Write memory/project_q282_scheduling_passthrough.md -> ok
05:46:26 Edit memory/MEMORY.md -> ERR <tool_use_error>File has not been read yet. Read it first before writing to it.</tool_use_error>
05:46:30 Read memory/MEMORY.md
05:46:36 Edit memory/MEMORY.md -> ok
Seven further sessions in the same 14-day window show the identical Write/Edit-memory-file → Edit-MEMORY.md → error → Read → retry shape.
Steps to Reproduce
- Use a project where auto-memory is active and
MEMORY.mdalready exists with content (so its content is injected into the session context under "# Memory"). - Ask Claude to remember something durable (e.g. "remember that we use X convention"), such that it writes a new memory file per its instructions.
- Observe the next tool call: an Edit (or Write) to
MEMORY.mdadding the index pointer line, without a prior in-conversation Read — the model already has the file's content in context. - The call fails with
File has not been read yet. Read it first before writing to it.; the model then Reads and retries successfully.
The failure requires the model to follow the instructions literally (skip the redundant Read); across two weeks of sessions this occurred at least 9 times on MEMORY.md alone, so it is the common path, not an outlier.
Claude Model
Not sure / Multiple models
Is this a regression?
No, this never worked
Last Working Version
_N/A_
Claude Code Version
Observed across 2.1.197, 2.1.202, 2.1.205, 2.1.209 (per transcript version fields over the 14-day window)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Other
Additional Information
- Enforcement appears inconsistent across builds/models: in a current session (Fable 5, same day the errors above were still occurring in parallel 2.1.209 sessions), Edit on a pre-existing never-Read file succeeded — the gate ran the old_string uniqueness check and applied the edit with no "has not been read" rejection — even though the session's own Edit/Write tool descriptions still document the rule as "the call will fail". So docs, instructions, and enforcement currently disagree in both directions depending on build.
- Related but distinct open issues (different triggers for the same gate): #73281 (truncated whole-file Read doesn't satisfy the gate — a Read did happen) and #76361 (read-state resets on branch switch/compaction/parallel sessions). This report is specifically about the auto-memory instructions directing an edit that the gate is guaranteed to reject on first save.