If you run Claude Code through a long coding session, sooner or later it starts spitting out File has been modified since read it. You need to re-read the file before you can edit it. over and over. A file that was editing cleanly five minutes ago suddenly fails on every Edit, and Claude burns tokens and rate limits re-reading the same file just to fail again.
In my own setup the errors clustered around two projects: a frontend repo with Prettier wired into editor.formatOnSave, and a folder living inside Dropbox that was being synced across two Macs. It is tempting to file this under "Claude Code bug," but once you sit with it for a while the trigger almost always lands on one of three settings. Knock them out in order and the error stops being a daily annoyance.
What the error is actually telling you
Before calling Edit or Write, Claude Code records the file's modification time (mtime) as of the last successful Read. When you then ask it to edit, it checks the current mtime against the recorded one. If they differ, it refuses the write — the file on disk is no longer what you were looking at.
So the error is not a bug. It is Claude Code's safety net firing because a third party changed the file in between your read and your write. The thing to fix is not Claude Code; it is whatever third party is touching the file behind its back.
From my own observation, that third party is almost always one of three things:
- A formatter that runs on save (Prettier / Black / gofmt / Biome)
- A cloud sync client writing back changes (Dropbox / iCloud Drive / Google Drive)
- A background process owned by another terminal (test watchers, dev servers, even a second Claude Code session)
Case 1: a formatter is rewriting the file out from under you
By far the most common cause. If VS Code has editor.formatOnSave set to true, the moment Claude Code writes the file, Prettier or Biome reformats and writes it back, bumping the mtime. The next Edit from Claude trips the guard. Repeat.
What worked for me was carving out a Claude Code workspace where format-on-save is off, while leaving my other projects untouched. A project-local .vscode/settings.json is the cleanest way:
{
"editor.formatOnSave": false,
"editor.formatOnPaste": false,
"editor.formatOnType": false,
"files.autoSave": "off"
}files.autoSave matters too. With afterDelay or onFocusChange, the editor writes the file without you asking, which is enough to invalidate Claude's last read. Set it to off while a Claude Code session is running.
If you do not want to lose Prettier entirely, push it onto Claude Code's PostToolUse hook. The formatter then only runs at a moment Claude Code already knows about, and there is no race:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true"
}
]
}
]
}
}This single change cut my File-modified errors on the frontend repo by roughly 90%.
Case 2: cloud sync is rewriting files in the background
My main development folder sits inside Dropbox, mostly because I run the same projects across two Macs. Dropbox, iCloud Drive, and Google Drive all do the same thing: when changes arrive from another device they write them back to disk, which updates the mtime. If Claude Code is mid-edit when that happens, it fails.
The sharpest edge here is having the same project open on a second machine. Just having the Finder window open on a secondary Mac will rewrite .DS_Store files often enough to shift the parent directory's mtime.
I changed my workflow in three steps:
First, pause cloud sync while a Claude Code session is running. On Dropbox, "Pause syncing" from the menu bar; on iCloud, going offline is faster than fighting individual files.
Second, do anything heavily automated outside the sync folder entirely. I now clone repos into ~/repos/ and run Claude Code there. Dropbox holds a periodic snapshot of finished work, not the live working tree.
Third, keep filesystem noise out of the repo. Adding .metadata_never_index to a folder convinces Spotlight to leave it alone, and a tight .gitignore plus .DS_Store/*.swp exclusions in your global ignore keep the small writes from cascading into Claude's Read calls.
Case 3: another process is writing in the background
Watch-mode processes — next dev, vite, jest --watch, tsc --watch, eslint --fix --watch — all rewrite files as a side effect of doing their job. next dev regenerates types under .next/types/. A tsc --watch --emit setup rewrites dist/ whenever a source file changes. If Claude Code happens to be reading those generated files, every rebuild raises the same File-modified error.
Three things helped here:
The first is the simplest: stop watch processes while Claude Code is generating code. Run code generation, verify, then restart the dev server. It feels old-fashioned, but on some machines it makes the error vanish entirely.
The second is telling Claude Code which directories not to touch. A CLAUDE.md at the project root, listing generated directories explicitly, is enough for the agent to give them a wide berth:
# Project Notes for Claude Code
## Do not read or edit these directories
- `.next/` — generated by Next.js; constantly rewritten by watch mode
- `dist/`, `build/` — build outputs; never edit by hand
- `coverage/` — Jest report output
- `node_modules/` — dependencies; do not touch directly
## When you need the dev server
1. Ask me to start it; do not start it yourself
2. While it is running, avoid Edit. If unavoidable, ask me to pause dev firstThe third is not running two Claude Code sessions against the same checkout. git worktree gives you a clean second working directory that lives in a different path, which lets two sessions coexist without fighting each other's mtimes.
What to do when the error still pops up
Even after all of the above, the error will occasionally fire. When it does, the fastest recovery is roughly this:
Start by simply telling Claude to re-read the file. A one-liner like "the file was updated, please Read it again before editing" makes Claude Code refresh its recorded mtime and try the edit again. That alone clears the majority of one-off cases.
If the same file errors repeatedly, find out what is writing to it. On macOS I keep a second terminal running fs_usage -w -f filesys /path/to/file, which prints every process that opens the file for write. On Linux, inotifywait -m /path/to/file does the same job. Once you have a process name, killing it is usually trivial.
As a last resort, copy the problematic file out to a scratch directory, let Claude Code finish its work there, and copy it back. It cuts the file off from formatters and sync clients entirely, which is enough to push through a long edit session without further interruptions.
The error stops being a Claude Code problem and starts being an environment problem
The first few times you hit this, the error looks like a small quirk of Claude Code. The longer you live with it, the more it starts to look like a question about your own development setup: are your tools designed to tolerate another agent writing files alongside them?
I have been an indie developer since 2014, running wallpaper apps that have crossed 50 million combined downloads, so my Macs are full of small conveniences I built up over the years: auto-save, format-on-save, cloud sync, watch-mode dev servers. Each of those was a clear win when only one human was at the keyboard. With an AI agent in the loop, every one of them turns into a potential race condition.
Turning off formatOnSave, killing watchers during generation, and moving repos out of Dropbox are all small individual calls. Stacked together they produce an environment that an AI agent can actually trust. I have come to read the File-modified error less as a Claude Code complaint and more as a useful signal pointing at the next boundary that needs sorting out.
Hope this helps anyone running into the same wall.