Bash tool kills every command after ~5s ("output file was replaced or could no longer be verified") when an EDR transiently hard-links new files
Version: 2.1.263 (also reproduced on 2.1.260). macOS 26.3 (Darwin 25.3.0), Apple Silicon. Genian Insights EDR installed (system extension).
Symptom
Every Bash tool call, foreground or background, sandboxed or with dangerouslyDisableSandbox, dies about 5 seconds after start with exit code 137 and:
Command killed: its output file was replaced or could no longer be verified
<bash output unavailable: output file /private/tmp/claude-501/<project>/<session>/tasks/<id>.output could not be read (unknown). This usually means another Claude Code process in the same project deleted it during startup cleanup.>
Short commands like pwd also fail: the command runs and the output file contains the correct output, but the read-back is reported as failed. No other Claude Code process is active in the project. The Read tool reads the same file fine.
Root cause
The EDR on this machine adds a second hard link to every newly created file on the boot volume for roughly 1 to 8 seconds, then removes it. stat on the task output file shows nlink=2 during that window, then nlink=1. Inode, size, owner, mode and content never change. Claude Code's output-file identity check (introduced in 2.1.251, "a sandboxed command cannot redirect or replace them") treats this state as a replaced file, sends SIGTERM then SIGKILL to the shell, and reports the output as unreadable with error code unknown.
Evidence
- Polling
stat -f %lon any new file (in /tmp, $HOME, ~/.claude, a 0700 dir) shows nlink 1 → 2 → 1 within ~8s. On a separately mounted APFS RAM disk or sparse image, nlink stays 1. - A trap inside the shell recorded SIGTERM at exactly +5s from the parent
claudeprocess; the loop kept writing after that until SIGKILL. - Headless reproduction with
claude -p "run: echo hi && sleep 7 && echo alive" --allowedTools 'Bash(echo:*)': - default tmp dir: killed, 137
CLAUDE_CODE_TMPDIR=~/cctmp(boot volume, 0700): killed, 137CLAUDE_CODE_TMPDIR=/Volumes/<apfs-ramdisk>/t: worksCLAUDE_CODE_TMPDIR=/Volumes/<apfs-sparseimage>/t: works
Expected
A transient extra hard link with unchanged dev/inode is not a replaced file. The check should compare device and inode (and possibly owner/mode) rather than failing on nlink > 1, or at least retry before killing the command. The error message blaming "another Claude Code process ... startup cleanup" is misleading here.
Workaround
Point CLAUDE_CODE_TMPDIR at a directory on a separately mounted volume (settings.json env works).
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗