[chrome-native-host] Unhandled EPIPE error on browser close crashes native host process
Description
When the browser is closed (or the tab with Claude Code extension is closed), the native host process (cli.js --chrome-native-host) crashes with an unhandled write EPIPE error instead of exiting gracefully.
Environment
- OS: Linux 6.17.0-14-generic
- Node.js: v18.20.8
- Claude Code: installed via npm-global
- Browser: Chrome (with Claude Code extension)
Steps to Reproduce
- Ensure the Claude Code Chrome extension is installed and the native host is registered (
com.anthropic.claude_code_browser_extension.json) - Open any web page in Chrome — the extension connects to the native host
- Close the browser (or the Chrome window)
- Observe the terminal / stderr output of the native host process
Expected Behavior
The native host process should detect that the browser has closed the pipe and exit cleanly (exit code 0, no output).
Actual Behavior
The process throws an unhandled error event and crashes with a non-zero exit code:
node:events:495
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at afterWriteDispatched (node:internal/stream_base_commons:160:15)
at writeGeneric (node:internal/stream_base_commons:151:3)
at Socket._writeGeneric (node:net:962:11)
at Socket._write (node:net:974:8)
at writeOrBuffer (node:internal/streams/writable:392:12)
at _write (node:internal/streams/writable:333:10)
at Writable.write (node:internal/streams/writable:337:10)
at Zz6 (file:///.../@anthropic-ai/claude-code/cli.js:6179:187)
at Socket.<anonymous> (file:///.../@anthropic-ai/claude-code/cli.js:6179:3842)
at Socket.emit (node:events:517:28)
Emitted 'error' event on Socket instance at:
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
errno: -32,
code: 'EPIPE',
syscall: 'write'
}
Root Cause
When Chrome closes the native messaging connection, the stdin/stdout pipe to the native host breaks. The host attempts a subsequent write to the closed socket, which emits an 'error' event on the Socket instance. Since no error listener is attached, Node.js treats it as an unhandled exception and terminates the process with a stack trace.
The fix is straightforward — attach an error handler to the socket (or process.stdout) used for native messaging communication:
process.stdout.on('error', (err) => {
if (err.code === 'EPIPE') process.exit(0);
});
Severity
Low — functionally harmless (the process exits regardless), but produces noisy error output in the user's terminal and may interfere with process supervisors or shell scripts that check exit codes.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗