[chrome-native-host] Unhandled EPIPE error on browser close crashes native host process

Resolved 💬 2 comments Opened Feb 24, 2026 by ikeniborn Closed Mar 24, 2026

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

  1. Ensure the Claude Code Chrome extension is installed and the native host is registered (com.anthropic.claude_code_browser_extension.json)
  2. Open any web page in Chrome — the extension connects to the native host
  3. Close the browser (or the Chrome window)
  4. 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.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗