macOS: voice dictation dies in every running session after the auto-updater replaces claude.exe ("No audio detected from microphone"; TCC denies the old PID)
Environment
- Claude Code 2.1.273 (sessions started on 2.1.272 and 2.1.273), npm global install (
/opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe) - macOS 26.5.1 (25F80), Apple Silicon (arm64), Terminal.app, sessions started from a zsh tab (not daemon-hosted)
- Voice via the native
audio-capture.nodepath, USB headset as default input - Several Claude Code sessions running in parallel, auto-updates enabled (default)
What happens
Voice works in a session, then silently stops working with:
No audio detected from microphone. Check that the correct input device is selected and that Claude Code has microphone access.
Only a fresh session helps. /voice off/on, /voice tap / /voice hold, and switching the default input device do not. Device, input level and Terminal's microphone permission (authValue=2) are fine.
Root cause (from the unified log)
A session's auto-updater reinstalls the package via npm-global and replaces claude.exe with a new file (new inode). Every session started before the swap keeps running the deleted old image. On its next recording start, coreaudiod asks tccd.system for the microphone right of that PID, gets an empty reply, and denies input. The IO context then starts without an input stream, the addon receives silence, and Claude Code reports "No audio detected".
Timeline, one session (PID 74472, started 08:56:30 local time):
08:58:29 … 09:01:25 six recordings, each "PublishRecordingClientInfo: Report client 74472 running: yes"
09:00:27 claude.exe replaced: inode 117853250 -> 118114267
~/.claude/.last-update-result.json:
{"path":"npm-global","outcome":"success","version_from":"2.1.272","version_to":"2.1.273"}
09:03:10 next recording attempt fails
coreaudiod at 09:03:10 (excerpt, repeated 5x per attempt):
coreaudiod (TCC) TCCAccessRequest() IPC
coreaudiod [com.apple.TCC:access] SEND: 0/7 synchronous to com.apple.tccd.system: request: msgID=431.6834, function=TCCAccessRequest, service=kTCCServiceMicrophone, target_token={pid:74472, auid:501, euid:501},
coreaudiod [com.apple.TCC:access] RECV: synchronous reply <dictionary: 0x…> { count = 0, transaction: 0, voucher = 0x0, contents =
coreaudiod (CoreAudio) HALS_IOContext.cpp:1491 Client is not granted access to the input device.
coreaudiod (CoreAudio) HALS_IOContext_Legacy_Impl::IOWorkLoopInit: 15076 … starting <- no PublishRecordingClientInfo follows
The same session at 09:00:24, before the swap, got a normal TCC decision:
tccd Handling access request to kTCCServiceMicrophone, from Sub:{com.apple.Terminal}Resp:{… com.apple.Terminal …}, ReqResult(Auth Right: Allowed (User Consent), …)
The same pattern (denials only for sessions older than the swap, fresh sessions record normally) appeared several times the same morning, e.g. an update run that finished at 08:04:19 (result file written after the file swap) with denials starting 08:04:17.
Why it keeps happening
The updater compares the running version with latest. A session started before an update considers itself outdated and reinstalls, even when the installed file is already at latest (here 2.1.272 -> 2.1.273 at 09:00:27, although 2.1.273 had been installed at 08:04:19). With several long-running sessions each swap cuts the microphone for every older session, and any remaining older session can trigger the next swap.
Steps to reproduce
- npm global install, auto-updates on, macOS.
- Start session A, confirm voice dictation works.
- Replace the binary while A is running (let a second, older session auto-update, or run
npm install -g @anthropic-ai/claude-code@latestto reinstall the same version). Step 3 is derived from the observed update runs; a manual reinstall was not tested separately. - Dictate in session A again → "No audio detected from microphone";
log show --predicate 'process == "coreaudiod"'showsClient is not granted access to the input devicefor A's PID. - Start session B → dictation works.
Expected
- The updater does not replace the running executable in place (versioned install path / atomic switch that leaves running images valid), or does not reinstall when the installed version already equals
latest. - If the microphone right is denied, the error says so (the
not granted accesscase is distinguishable from real silence) and suggests restarting the session, instead of pointing at input device selection.
Workaround
"env": { "DISABLE_AUTOUPDATER": "1" } in ~/.claude/settings.json, update manually right before restarting all sessions.
Related
#86217 (same symptom via a launchd-reparented recorder, different trigger), #89635 (addon handle memoized for process lifetime), #38054 / #80366 / #65331 (symptom "only a restart helps").
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗