[BUG] audio-capture.node aborts the whole VS Code extension host when no audio device is present (Linux x64, Node 24, Claude v2.1.282)
Preflight Checklist
- [x] I have searched existing issues. It was reported in April (note below)
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Closest prior report is #38685 (Linux x64, Node 22, v2.1.83), closed as not planned/stale in April without a fix. Same assertion, seems to be the same root cause. It still reproduces on the current versions.
On a host with no audio capture device, calling startRecording() into the bundled audio-capture.node aborts the entire VS Code extension host process, not just the voice feature. Every Claude Code session in that window dies with it.
It's a native abort() (SIGABRT) from a node CHECK, so it cannot be caught by any JS-level error handling in the extension.
Chain of events:
microphoneAuthorizationStatus()returns3(authorized) — Linux has no macOS-style permission gate, so nothing blocks the attempt.- Capture init enumerates devices, but fails to open one.
- Setup bails, and the NAPI thread-safe function is never created, remaining
nullptr. - During cleanup, the path calls
napi_release_threadsafe_function()unconditionally. - Node's
CHECK(func != nullptr)fires →abort()→ SIGABRT.
Note that this was run on a LXC container (on Proxmox if that's relevant); /proc/asound is not namespaced. ALSA sees the host's sound cards even though /dev/snd doesn't exist. This results in a device list that is populated while every open fails.
Also relevant: the extension declares no extensionKind, so it runs in the remote extension host. Under Remote-SSH, voice capture is attempted on the remote machine, which in a headless container has no audio device at all.
What Should Happen?
It should throw a normal error the extension can catch and alert the user that "no microphone found" or some similar message, while leaving everything else running.
Error Messages/Logs
.../server/node[2807553]: napi_status napi_release_threadsafe_function(
napi_threadsafe_function, napi_threadsafe_function_release_mode)
at ../src/node_api.cc:1466
Assertion failed: (func) != nullptr
----- Native stack trace -----
1: 0x9283e7 node::Assert(node::AssertionInfo const&) [.../server/node]
2: 0x8cc242 napi_release_threadsafe_function [.../server/node]
3: 0x71f4618e123a [.../audio-capture/x64-linux/audio-capture.node]
4: 0x71f4618cac00 [.../audio-capture/x64-linux/audio-capture.node]
5: 0x71f4618c136e [.../audio-capture/x64-linux/audio-capture.node]
6: 0x8a0811 [.../server/node]
#38685 has the same assertion at `node_api.cc:1410` — different line number
because that was Node 22 and I'm on Node 24, but it's the same failure.
Steps to Reproduce
Any Linux box with no /dev/snd — headless server, LXC or Docker container,
VM without audio passthrough:
node -e "require('./resources/audio-capture/x64-linux/audio-capture.node').startRecording()"
After about 50ms, it crashes. There's no retry, loop, nothing. It just dies. I've found that triggering voice from the VS Code UI kills the extension host too.
Worth noting that the person in #38685 had a working mic (arecord and PulseAudio both fine) and still hit this, so I guess missing devices aren't required.
### Claude Model
Opus
### Is this a regression?
No, this never worked
### Last Working Version
_No response_
### Claude Code Version
2.1.282 ( I originally tested it on 2.1.281, but when 2.1.282 came out to stay in line with the most recent version requirements I ran a quick test and still ran into the bug )
### Platform
Anthropic API
### Operating System
Other Linux
### Terminal/Shell
Other
### Additional Information
Terminal doesn't seem relevant to this issue as it was triggered on VS Code using Remote-SSH with Claude-Code extension.
| Node | Source | Assertion line |
|---|---|---|
| v24.20.0 | bundled with VS Code server | `node_api.cc:1466` |
| v22.23.1 | system node | `node_api.cc:1412` |
| v22.19.0 | reporter of #38685 | `node_api.cc:1410` |
Same assertion each time — the line number just tracks the Node source version.
The module I tested is the extension's own copy: `~/.vscode-server/extensions/anthropic.claude-code-2.1.281-linux-x64/resources/audio-capture/x64-linux/audio-capture.node` The CLI ships a separate copy; #38685 was the CLI path (`/voice`), this is the extension path.
---
Diagnosis and testing done with Claude Code — I hit the crash and worked out roughly what was happening, Claude ran the repro and the core-dump analysis.