Headless claude -p deadlocks in uninterruptible openat on macOS; interactive sessions unaffected
Date: 2026-08-24
Summary
Every headless invocation (claude -p) on this machine deadlocks partway into the session:
main thread blocked forever in openat$NOCANCEL, 0% CPU, no TCP connections, no child
processes. Interactive sessions on the same machine, same account, are unaffected.
8/8 reproductions: 5 via a no-mistakes pipeline daemon spawning claude -p --output-format, and 3 spawned directly from a
stream-json --json-schema ... --dangerously-skip-permissions
shell with stdout redirected to a file (with and without --debug, with and withoutCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1).
Signature
sample <pid>: main thread parked inopenat$NOCANCEL(1500+/1500+ samples), JIT (JS)
frames above; worker threads idle in kevent64/pool waits.
- No TCP sockets open (
lsof); not a network hang. - No child processes; not a tool-subprocess hang.
SIGKILLsometimes fails to reap the process (uninterruptible syscall).- Freeze point varies by run: after ~2 tool rounds (transcript event 19, last =
total_tokens_reminder attachment), at ai-title (event 9), or at atis-latch (event 20).
Always coincides with concurrent background activity (session-title request in flight,
statsig/bootstrap fetch, atomic ~/.claude.json rewrite).
- With
--debug: log stops mid-stream right after two concurrent/v1/messagesrequests
(source=generate_session_title + source=sdk) both received first bytes.
Ruled out
- no-mistakes daemon (reproduces with plain
claude -pfrom a shell) - claude version regression (2.1.235 and 2.1.241 both freeze)
- permission-prompt deadlock (
--dangerously-skip-permissionspresent in pipeline repros) - stdout backpressure (reproduces with stdout redirected to a regular file)
- hung file provider (Google Drive + fileproviderd restarted; CloudStorage lists fine)
- FIFOs / dead symlinks in cwd, skills, agents, plugins trees (none exist)
- keychain-db file locks (no holders)
- nonessential traffic (
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1still freezes)
Not yet done (needs sudo)
fs_usage/spindump or lldb attach to capture the blocked path argument — lldb attach is
denied by SIP for a same-user attach on this machine.
Repro
cd <any git repo>
echo 'Read README.md, then read pyproject.toml, then reply with one sentence.' | claude -p
# hangs forever; sample the pid to see openat$NOCANCEL
Impact
Any local tooling that drives claude -p (review pipelines, cron jobs, CI-style local gates)
wedges silently. Workaround in use: pipeline agent switched to codex; Claude review still
applied via GitHub Actions (claude-review.yml) and interactive sessions.