Voice dictation permanently freezes TUI: main thread blocked in synchronous CoreAudio call (AudioUnitSetProperty) while opening microphone
Summary
Holding Space to start voice dictation permanently freezes the entire TUI: the footer stays on "keep holding…" forever, no keystroke is processed, Ctrl+C does not recover, and the only way out is killing the process. sample shows the main thread blocked in a synchronous CoreAudio call with no timeout while opening the microphone. When the audio HAL is slow to respond (a third-party audio client had degraded coreaudiod state), that call never returns and the whole input loop dies with it.
This looks like the root cause behind #20476 (closed), which described the same symptom without a stack trace.
Environment
- Claude Code 2.1.226 (native build,
claude.exevia Homebrew) - macOS 26.6.2 (25G83), Apple Silicon (arm64)
- Terminal.app, hold-to-talk mode (default Space binding), claude.ai account
Stack sample of the frozen process
100% of samples (1674/1674) on the main thread, blocked here:
1674 Thread DispatchQueue_1: com.apple.main-thread (serial)
... claude.exe frames ...
??? (in .5ed67dedd7cb7578-0.node) <- bundled native audio module
??? (in .5ed67dedd7cb7578-0.node)
AudioUnitSetProperty (in AudioToolboxCore) + 484
??? (in CoreAudio)
??? (in CoreAudio)
??? (in CoreAudio)
AudioDeviceGetProperty (in CoreAudio) + 204
HALPlugIn::ObjectHasProperty(HALObject const&, AudioObjectPropertyAddress const&) const + 44
HAL_HardwarePlugIn_ObjectHasProperty(AudioHardwarePlugInInterface**, unsigned int, AudioObjectPropertyAddress const*) + 480
The process sits in AudioUnitSetProperty → AudioDeviceGetProperty → HALPlugIn::ObjectHasProperty indefinitely (observed >10 minutes, 0% CPU, state S). Since this runs on the same thread that services terminal input, the TUI freezes completely — matching the "no spinner, completely unresponsive" reports in #20476.
Controlled reproduction
The freeze correlates with degraded CoreAudio daemon state caused by a long-running third-party audio client (an app with a per-app volume mixer that inserts itself into CoreAudio; coreaudiod had accumulated 10+ hours of CPU time). Space key hold was simulated with synthetic CGEvents carrying the autorepeat flag, so all three tests are identical at the input layer:
| Test | Conditions | Result |
|---|---|---|
| A | third-party audio-mixer app running for ~2 weeks | permanent freeze, stack above |
| B | no third-party audio clients | dictation works end-to-end (mic opens, transcribes, inserts) |
| C | same app freshly relaunched | dictation works — the bad HAL state builds up over time |
So the external app is the trigger, but the defect is in Claude Code: a hostile-or-slow audio HAL should never be able to hang the input loop.
Expected behavior
- Open the audio device asynchronously (or on a worker thread) with a timeout.
- On timeout, cancel dictation, show an error ("microphone unavailable"), and keep the TUI responsive.
Workarounds found
claude --continueafter killing the frozen process restores the session.- Quitting/relaunching the offending audio client (or disabling its mixer feature) clears the HAL state and dictation works again.
Happy to provide the full sample output or run an instrumented build if useful.