[BUG] Claude in Chrome native host on Windows fails to claim bridge pipe — `ERR_INVALID_ARG_TYPE` from Bun's `node:net.listen` — missing stale-pipe cleanup branch for `win32`
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [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?
On Windows, claude.exe --chrome-native-host (the Chrome Native Messaging host spawned by the Claude browser extension) exits silently within milliseconds of launch. It tries to create a Unix-style "socket listener" on the named pipe \\.\pipe\claude-mcp-browser-bridge-<USERNAME> but server.listen() throws TypeError: ERR_INVALID_ARG_TYPE. The browser extension therefore never has a working channel to Claude Code, and every mcp__claude-in-chrome__* tool call returns the canned "Browser extension is not connected. Please ensure the Claude browser extension is installed and running..." error — even though the extension, the manifest, the native-messaging registry entry, claude.ai login, and the claude --chrome session are all correctly set up.
Inspection of the disassembled CLI code shows the native host has a platform() !== "win32" cleanup branch that unlinks stale Unix sockets before listening. There is no equivalent cleanup branch for Windows, so on Windows the host has to compete for a singleton named-pipe with whichever process spawned first (typically the active claude --chrome session). Whichever process registers second crashes silently.
What Should Happen?
After the extension is reloaded with claude --chrome running:
- The native messaging host (
claude.exe --chrome-native-host) should be spawned by Chrome and remain alive, holding stdin/stdout pipes to Chrome and either holding or connecting to the bridge pipe. mcp__claude-in-chrome__tabs_context_mcpshould return a JSON list of open tabs in the user's MCP tab group, creating the group if needed.- Subsequent browser tools (
tabs_create_mcp,navigate, etc.) should drive the browser.
Error Messages/Logs
### Captured stderr from a manual invocation of the native host
Captured by running `claude.exe --chrome-native-host` directly from PowerShell with stderr redirected. (Chrome swallows stderr when it spawns native messaging hosts, which is why this isn't normally visible.)
[Claude Chrome Native Host] Initializing...
[Claude Chrome Native Host] Creating socket listener: \\.\pipe\claude-mcp-browser-bridge-<USERNAME>
[Claude Chrome Native Host] Socket server error: <CLI bundle code excerpt — see below>
TypeError: Failed to listen at \\.\pipe\claude-mcp-browser-bridge-<USERNAME>
code: "ERR_INVALID_ARG_TYPE"
at listen (unknown:1:1)
at node:net:1339:30
at listenInCluster (node:net:1423:24)
at listen (node:net:1331:20)
at B:/~BUN/root/src/entrypoints/cli.js:9056:1166
at Promise (unknown:1:11)
at start (B:/~BUN/root/src/entrypoints/cli.js:9056:1139)
at B:/~BUN/root/src/entrypoints/cli.js:9056:357
at u7 (B:/~BUN/root/src/entrypoints/cli.js:128:6952)
at OCA (B:/~BUN/root/src/entrypoints/cli.js:9056:262)
Bun v1.3.14 (Windows x64 baseline)
### MCP layer log (for context — shows the tool round-trips fine; the failure is below the MCP layer)
`C:\Users\<USERNAME>\AppData\Local\claude-cli-nodejs\Cache\<PROJECT>\mcp-logs-claude-in-chrome\<TS>.jsonl`:
{"debug":"In-process Chrome MCP server started","timestamp":"…","sessionId":"…","cwd":"C:\\"}
{"debug":"Starting connection with timeout of 30000ms",...}
{"debug":"Successfully connected (transport: stdio) in 2166ms",...}
{"debug":"Connection established with capabilities: {\"hasTools\":true,…,\"serverVersion\":{\"name\":\"Claude in Chrome\",\"version\":\"1.0.0\"}}",...}
{"debug":"Calling MCP tool: tabs_context_mcp",...}
{"debug":"Tool 'tabs_context_mcp' completed successfully in 212ms",...}
So at the MCP-protocol level everything looks healthy; the failure is in the in-process MCP server's connection to the (non-existent) native host.
### Relevant disassembled native-host code
From the Bun-bundled CLI (`B:/~BUN/root/src/entrypoints/cli.js`), reconstructed approximately:
async function OCA() {
return u7("chrome_native_host_run", async () => {
tj("Initializing...");
let server = new Jk_();
let stream = new Lk_();
await server.start();
while (true) {
let msg = await stream.read();
if (msg === null) break;
await server.handleMessage(msg);
}
await server.stop();
});
}
class Jk_ {
mcpClients = new Map();
nextClientId = 1;
server = null;
running = false;
socketPath = null;
async start() {
if (this.running) return;
this.socketPath = w66(); // returns e.g. "\\.\pipe\claude-mcp-browser-bridge-<USERNAME>"
if (A26.platform() !== "win32") {
// -------- POSIX cleanup branch --------
let dir = u38();
await Dh.unlink(dir).catch(() => {});
await Dh.mkdir(dir, { recursive: true, mode: 0o700 });
await Dh.chmod(dir, 0o700).catch(() => {});
try {
let entries = await Dh.readdir(dir);
for (let name of entries) {
if (!name.endsWith(".sock")) continue;
let pid = parseInt(name.replace(".sock", ""), 10);
if (isNaN(pid)) continue;
try { process.kill(pid, 0); }
catch {
await Dh.unlink(Xk_.join(dir, name)).catch(() => {});
tj(`Removed stale socket for PID ${pid}`);
}
}
} catch {}
// --------------------------------------
}
// NOTE: no equivalent cleanup / takeover branch for Windows.
tj(`Creating socket listener: ${this.socketPath}`);
// …
// server.listen(this.socketPath) → throws ERR_INVALID_ARG_TYPE on Windows when path is in use,
// or the path-shape Bun's listen accepts on Windows is different.
}
}
### Process / pipe state captured at the moment of failure
ProcessId ParentProcessId Name CreationDate CommandLine
--------- --------------- ---------- -------------------- -----------------------------------------------
100764 3100 claude.exe 2026-05-12 22:21:00 "C:\Users\<USERNAME>\.local\bin\claude.exe" --chrome
(no claude.exe --chrome-native-host process is alive after the extension reload)
Named pipes:
\\.\pipe\chrome.nativeMessaging.in.<HEX> ← created by Chrome for the just-spawned (and now-dead) native host
\\.\pipe\chrome.nativeMessaging.out.<HEX> ← created by Chrome for the just-spawned (and now-dead) native host
\\.\pipe\claude-mcp-browser-bridge-<USERNAME> ← still alive, presumably held by PID 100764 (claude --chrome)
### Native-host parent process tree (from an earlier moment when the host WAS briefly alive)
PID 7348 chrome.exe (background)
└── PID 81932 chrome.exe (browser)
└── PID 66692 cmd.exe /d /s /c ""…\chrome-native-host.bat" chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/ --parent-window=0"
< \\.\pipe\chrome.nativeMessaging.in.<HEX>
> \\.\pipe\chrome.nativeMessaging.out.<HEX>
└── PID 3736 claude.exe --chrome-native-host (exited within ~1s)
Steps to Reproduce
Steps to Reproduce (minimal)
This was reproduced repeatedly across multiple browser-restart and CLI-restart cycles. The minimal sequence:
- On a Windows 11 machine, install the Claude Code CLI (
claude.exev2.1.140 from the installer). - Install the Claude in Chrome extension (
https://claude.ai/chrome) in Google Chrome. - Sign in to
claude.aiin Chrome with the same account that Claude Code is authenticated against. - Open PowerShell and run
claude --chrome. Let the session reach the prompt. - In Chrome, open
chrome://extensions, find the Claude card and click the reload icon. - In the active Claude Code session, call any browser tool, e.g.
mcp__claude-in-chrome__tabs_context_mcp.
Observed: Tool call returns the "Browser extension is not connected…" error. No claude.exe --chrome-native-host process is alive after the extension reload, even though Chrome created new \\.\pipe\chrome.nativeMessaging.in/out.<HEX> pipes for the launch.
Variants attempted (all reproduce the same end state):
- Start
claude --chromefirst, then open Chrome. - Start Chrome first, then
claude --chrome. - Quit everything, run
Stop-Process claude -Force, restart in a specific order. - Install the extension in Microsoft Edge Stable instead of Chrome (with
claude.ailogged in there). - Close all browsers and only run one at a time.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.140
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Windows Terminal
Additional Information
Environment
| Field | Value |
|---|---|
| OS | Windows 11 Pro, version 10.0.26200 |
| Architecture | x64 |
| Claude Code version | 2.1.140 (Claude Code) |
| Claude Code binary path | C:\Users\<USERNAME>\.local\bin\claude.exe (binary mtime 2026-05-12 18:29) |
| Runtime embedded in claude.exe | Bun v1.3.14 (Windows x64 baseline) |
| Interface | Claude Code CLI in PowerShell (claude --chrome) |
| Terminal emulator | Windows Terminal / PowerShell 5.1 |
| Browser | Google Chrome (C:\Program Files\Google\Chrome\Application\chrome.exe) — also tested with Microsoft Edge Stable (C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe) and Chromium build (C:\games\chrome-win\chrome-win\chrome.exe) |
| Extension ID | fcoeoabgfenejglbffodgkkbkcdhcgfn |
| Extension version installed | 1.0.70 |
| Plan (account) | Claude Pro |
| Subscription verified | Yes — same account in Chrome's claude.ai tab as in Claude Code OAuth credentials |
| Session ID | c2c42119-7b29-4395-9242-80f5b9fc8a4d |
| Session PID | 100764 |
Configuration verified before diagnosis
All standard prerequisites verified by reading files on disk and the registry. These are NOT the source of the failure but are listed so the developer doesn't have to re-check.
Native messaging host registry
HKCU\Software\Google\Chrome\NativeMessagingHosts\com.anthropic.claude_code_browser_extension
(Default) = C:\Users\<USERNAME>\AppData\Roaming\Claude Code\ChromeNativeHost\com.anthropic.claude_code_browser_extension.json
HKCU\Software\Chromium\NativeMessagingHosts\com.anthropic.claude_code_browser_extension ✓ also registered
HKCU\Software\Microsoft\Edge\NativeMessagingHosts\com.anthropic.claude_code_browser_extension ✓ also registered
Native messaging manifest
C:\Users\<USERNAME>\AppData\Roaming\Claude Code\ChromeNativeHost\com.anthropic.claude_code_browser_extension.json:
{
"name": "com.anthropic.claude_code_browser_extension",
"description": "Claude Code Browser Extension Native Host",
"path": "C:\\Users\\<USERNAME>\\.claude\\chrome\\chrome-native-host.bat",
"type": "stdio",
"allowed_origins": [
"chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/"
]
}
Native host wrapper batch file
C:\Users\<USERNAME>\.claude\chrome\chrome-native-host.bat:
@echo off
REM Chrome native host wrapper script
REM Generated by Claude Code - do not edit manually
"C:\Users\<USERNAME>\.local\bin\claude.exe" --chrome-native-host
Side note: the wrapper does not forward arguments (%*is missing) so the extension origin URL Chrome passes (chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/ --parent-window=0) never reachesclaude.exe. This may or may not be intended — origin validation could be done some other way — but it is worth checking. It is not the proximate cause of the bug described here.
Extension manifest
C:\Users\<USERNAME>\AppData\Local\Google\Chrome\User Data\Default\Extensions\fcoeoabgfenejglbffodgkkbkcdhcgfn\1.0.70_0\manifest.json includes the nativeMessaging permission, signed with the pinned key field (so the extension ID is stable across reinstalls/browsers). Looks correct.
Account match
The user's claude.ai session in Chrome is signed in to the same account as Claude Code's OAuth credentials (C:\Users\<USERNAME>\.claude\.credentials.json shows a subscriptionType: "pro" token; the same account profile is visible in chrome://settings and on claude.ai).
Actual Behavior (bug behaviour)
- Chrome successfully spawns the wrapper
cmd.exe /d /s /c "...\chrome-native-host.bat ..."with stdin/stdout attached to fresh\\.\pipe\chrome.nativeMessaging.in/out.<HEX>pipes. - The wrapper invokes
claude.exe --chrome-native-host. claude.exelogsInitializing...andCreating socket listener: \\.\pipe\claude-mcp-browser-bridge-<USERNAME>to stderr.server.listen(...)throwsTypeError: ERR_INVALID_ARG_TYPE.- The process exits in well under a second. No Windows Event Log entry is generated (it's a clean error path, not a crash).
- Chrome's native-messaging stdio pipes remain open with no peer, so the extension reports "disconnected."
claude-mcp-browser-bridge-<USERNAME>remains in\\.\pipe\listings (apparently still held by theclaude --chromeClaude Code session).- The MCP tool round-trips successfully at the Claude Code MCP protocol layer (logged in
…\claude-cli-nodejs\Cache\<PROJECT>\mcp-logs-claude-in-chrome\*.jsonlasTool 'tabs_context_mcp' completed successfully in 212ms) — but the tool body returns the "Browser extension is not connected" error string because the bridge has no connected native host.
What I've Already Tried
- Reload extension in Chrome (
chrome://extensions→ reload icon on Claude card). Verified newchrome.nativeMessaging.*.<HEX>pipes were created each time. Native host died each time. No fix. - Toggle extension off then on. Same outcome.
- Full Chrome restart (close all windows, verify no
chrome.exeinGet-Process, reopen). No fix. - Killed all
claude.exehelpers (Get-Process claude | Stop-Process -Force), then ranclaude --chromefrom a fresh PowerShell before opening any browser. Then opened Chrome and reloaded the extension. No fix — sameERR_INVALID_ARG_TYPE. - Reverse order: opened Chrome with extension first, then started
claude --chromeafterwards. No fix. - Switched browsers: installed the same extension in Microsoft Edge Stable (native-messaging is registered for Edge in
HKCU\Software\Microsoft\Edge\NativeMessagingHosts). Signed in toclaude.aiin Edge with the same account, closed and reopened Edge. Edge spawned the native host but it was actuallycmd.exewhose grandparent was Google Chrome not Edge — i.e. whichever Chromium-based browser instance was already running ended up servicing the native messaging call. Either way: same failure. - Verified the Chromium build (
C:\games\chrome-win\…) extension was not creating a competing native host. It wasn't (noclaude.exechild ofchromium.exe). - Looked for stale lock/state files in
C:\Users\<USERNAME>\.claude\chrome\— there are none beyond the bat file. Looked for*.lock,*bridge*,*chrome*files; onlytasks/*/.lockfiles (unrelated) and the bat itself. - Looked at Windows Event Log for
Application Error,.NET Runtime, andWindows Error Reportingprovider entries in the last 30 min mentioningclaude— none. This confirms the native host exits cleanly via the JS error path, not via a process crash. - Read MCP debug logs at
C:\Users\<USERNAME>\AppData\Local\claude-cli-nodejs\Cache\<PROJECT>\mcp-logs-claude-in-chrome\*.jsonl. Eachtabs_context_mcpcall is logged as "completed successfully" with a small latency — confirming the failure is not at the MCP layer; the in-process MCP server is finding no connected native host on the bridge. - Manually invoked
claude.exe --chrome-native-hostfrom PowerShell (outside Chrome) with stderr redirected — this is what produced theERR_INVALID_ARG_TYPEstack trace above. This was the diagnostic that finally pinned down the root cause.
Possible Cause / Hypothesis for Claude developers
There are two distinct, possibly compounding issues:
Hypothesis A (primary): Windows is missing the stale-pipe cleanup branch
Jk_.start() in the bundled CLI clearly has a POSIX cleanup branch (platform() !== "win32" → unlink dir, recreate, prune dead-PID .sock files). The Windows path falls straight through to server.listen(this.socketPath). When any other process is already holding \\.\pipe\claude-mcp-browser-bridge-<USERNAME> — for example the active claude --chrome session — listen fails. Two suggested fixes:
- Mirror the POSIX takeover semantics on Windows. On Windows the OS auto-cleans pipes when the owning process exits, so the equivalent is "if listen fails because the path is in use, decide whether to (a) connect-as-client to the existing server, or (b) bail out with a clearer error and tell Chrome the host isn't usable right now."
- Decide which role owns the pipe. Right now both
claude --chromeandclaude --chrome-native-hostapparently want to be the server. Pick one canonical server (the native host is the natural choice, since Chrome spawns it on demand) and haveclaude --chromeconnect as a client with retry.
Hypothesis B (also worth investigating): Bun-on-Windows net.listen accepts a different argument shape
The error ERR_INVALID_ARG_TYPE is surprising for a string pipe path that looks valid. It is normally what Node throws when listen()'s first arg is null/undefined/wrong-type, not for EADDRINUSE. Possibilities:
w66()returns aBufferor path-like that Bun's win32netlayer rejects, but Node would have accepted.- Bun on Windows expects an options object
{ path: "..." }rather than the bare path string. - A regression in Bun v1.3.14's win32
node:netshim.
If A is the underlying cause but the error is being reshaped through Bun's compatibility layer into ERR_INVALID_ARG_TYPE, fixing A would still resolve the user-visible symptom. If B is independent, it should also be fixed because the error message is actively misleading (it implies a programmer error in an arg passed to listen, when it might just be address-in-use).
Wrapper-script argument forwarding (minor; document only)
chrome-native-host.bat does not contain %*, so the extension origin URL Chrome passes (chrome-extension://fcoeoabgfenejglbffodgkkbkcdhcgfn/) and --parent-window=0 are never forwarded to claude.exe. If the host is meant to validate the calling extension origin, this is broken too. Not the proximate cause of the listen failure, but worth fixing in the same pass.
Additional Context
- The bat file and JSON manifest were generated together (same mtime,
2026-05-12 20:54:42) — apparently whenclaude --chromewas first invoked on the v2.1.140 build ofclaude.exe(binary mtime2026-05-12 18:29). So registration is self-installed by the CLI; the user did not edit it. - The Chromium-based browser ecosystem on this machine includes Google Chrome, Microsoft Edge Stable, and a portable Chromium build. All three have
com.anthropic.claude_code_browser_extensionregistered under their respectiveHKCU\Software\<Browser>\NativeMessagingHostskeys (Chrome, Chromium, Edge). The bug reproduces regardless of which browser is the one with the extension active. - The Claude Desktop Electron app (
C:\Program Files\WindowsApps\Claude_*\app\Claude.exe) was also running during some of the reproductions. It is unrelated — it does not touch theclaude-mcp-browser-bridge-*pipe — but mentioning it here in case it's relevant for ruling out conflicts. - The user's PowerShell session is PowerShell 5.1 (Windows PowerShell, not pwsh 7). Claude Code's CLI runs fine but is launched via the standard
claudeshim. - The user has a Pro Claude.ai subscription. Both browser and CLI are signed in to the same account. There is no SSO/identity mismatch.
- Anonymization in this report:
<USERNAME>substitutes the actual Windows username;<HEX>substitutes Chrome's native-messaging pipe-instance hash;<PROJECT>substitutes the cwd-mangled project directory name underclaude-cli-nodejs\Cache\;<TS>substitutes ISO-8601 log filenames. The extension ID and Claude Code version are not anonymized because they are public/non-identifying.
Suggested Repro Tester for Anthropic
A minimal Windows VM reproduction:
# 1. Install claude.exe v2.1.140 and authenticate.
# 2. Install the Claude Chrome extension in Google Chrome.
# 3. Sign into claude.ai with the same account in Chrome.
# 4. Start an interactive session that will hold the bridge pipe:
Start-Process -FilePath "$HOME\.local\bin\claude.exe" -ArgumentList "--chrome"
# 5. Confirm the bridge pipe exists:
Get-ChildItem '\\.\pipe\' | Where-Object Name -match 'claude-mcp-browser-bridge'
# 6. Now manually run the native host, the same way Chrome does, and capture stderr:
& "$HOME\.local\bin\claude.exe" --chrome-native-host 2>&1 |
Tee-Object -FilePath $env:TEMP\claude-nh.log
Expected output: TypeError: Failed to listen at \\.\pipe\claude-mcp-browser-bridge-<USERNAME> with code: "ERR_INVALID_ARG_TYPE".
Severity / Impact
Hard blocker for "Claude in Chrome" on Windows. Every browser tool (tabs_context_mcp, tabs_create_mcp, navigate, get_page_text, javascript_tool, gif_creator, etc.) returns the canned "not connected" error, regardless of correct setup. The user cannot use the feature at all until this is fixed upstream.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗