[SOLVED] Claude in Chrome "not connected" on Windows: stale oauth:tokenCache causes a 401 loop — fix inside
TL;DR — this is SOLVED, here is the fix
If list_connected_browsers / tabs_context_mcp returns "Claude in Chrome is not connected" on Windows and you have already reinstalled the extension, re-signed in, restarted Chrome and rebooted — stop, none of that is the problem.
Two stale encrypted OAuth caches in Claude Desktop's config.json put the app in an endless 401 loop. Delete them and it works:
# 1. Fully quit Claude Desktop first.
$cfg = "$env:LOCALAPPDATA\Packages\Claude_<pkg>\LocalCache\Roaming\Claude\config.json"
# 2. Back up byte-for-byte
Copy-Item $cfg "$cfg.bak-$(Get-Date -Format yyyyMMddTHHmmss)"
# 3. Remove ONLY these two keys, keep everything else:
# oauth:tokenCache
# oauth:tokenCacheV2
# 4. Start Claude Desktop. It reissues fresh tokens by itself.
Verification after restart: /api/oauth/profile returns 200 instead of 401, and list_connected_browsers returns your browser. Rollback is restoring the backup.
Total time: about a minute. We spent two hours before finding it, because the error message points at the wrong thing (see below).
---
Why the error message sends everyone the wrong way
This is the most expensive part of the bug, and it is a one-line fix.
list_connected_browsers calls ensureConnected() first:
- success → returns JSON; an empty roster is
[] - failure → returns the generic
onToolCallDisconnected()text
That generic text is:
The Chrome extension isn't reachable right now. […] the extension is likely not installed or not signed in. 1. Install the Claude in Chrome extension […] 2. Open the Claude side panel in Chrome and sign in with the same account as this app.
It is not a statement about the extension. It is emitted when Claude Code's own bridge client fails to connect or authenticate. But it reads as a diagnosis of the user's setup, so every user does exactly what it says — reinstall, re-login, restart Chrome — and none of it can possibly help.
Reading the closed duplicates below, the same pattern repeats in nearly all of them: users verify the extension and login exhaustively, because the message told them to.
Ask: distinguish "client failed to connect/authenticate" from "connected, zero browsers", and do not blame the user's extension when the failure is local.
---
Root cause of the connection failure
After a hard reboot plus a re-authentication, config.json retained two stale encrypted OAuth caches: oauth:tokenCache and oauth:tokenCacheV2.
- The app polled
/api/oauth/profileevery ~30s and received401. - The current version clears the token cache automatically only on
403, not on401. - So it looped indefinitely on a cache it would never invalidate.
- Fresh, valid credentials in
~/.claude/.credentials.jsonwere present the whole time and simply unused.
Ask: invalidate the cached token on 401 as well (or on any auth failure), instead of 403 only.
---
Second, independent defect: the integration is silently gated off in Desktop
Separate from the above, Claude Code launched by Claude Desktop never enables Claude in Chrome at all.
The gate (from the shipped bundle, order matters):
function qBe(e){
if(!fKt()) return false; // 1. OAuth scope check
if(e===true) return true; // 2. --chrome
if(e===false) return false; // --no-chrome
if(CLAUDE_CODE_ENABLE_CFC===true) return true; // 3. env var
if(CLAUDE_CODE_ENABLE_CFC===false) return false;
if(De()) return false; // 4. ← returns true under Desktop
let o=ie();
if(o.claudeInChromeDefaultEnabled!==undefined) // 5. never reached
return o.claudeInChromeDefaultEnabled;
return false;
}
Observed:
- No
claude.exeprocess spawned by Desktop carries--chrome(verified across all running processes). - No
--claude-in-chrome-mcpchild process exists. - The user setting
claudeInChromeDefaultEnabledwas alreadytrueand is never consulted, becauseDe()short-circuits first. - The browser tools are still advertised in the tool list and, when called, emit the misleading text above.
Workaround, since the env var is checked before De():
[Environment]::SetEnvironmentVariable('CLAUDE_CODE_ENABLE_CFC','true','User')
# then fully restart Claude Desktop
Confirmed by A/B: the same binary run headless without --chrome but with the env var returns the browser; without the env var the MCP server is not registered at all.
Ask: Desktop should honour claudeInChromeDefaultEnabled, or pass --chrome.
---
Third, minor: Desktop ships a dangling native-messaging registration
HKCU\Software\Google\Chrome\NativeMessagingHosts\com.anthropic.claude_browser_extension points at
…\LocalCache\Roaming\Claude\ChromeNativeHost\com.anthropic.claude_browser_extension.json
which the installation never creates — the folder contains only chrome-native-host.exe. Authoring the JSON by hand does make Chrome launch the host, but it does not affect list_connected_browsers, because the normal transport is the hosted bridge, not native messaging.
Package is SignatureKind: Developer, so this may be specific to that distribution channel. Same finding independently reported in #58968.
---
For anyone debugging this: how the connection actually works
Worth stating, because it invalidates most of the obvious guesses.
The primary transport is not native messaging. Extension and Claude Code each open an independently authenticated WebSocket to:
wss://bridge.claudeusercontent.com/chrome/<accountUuid>
list_connected_browsers sends list_extensions over that socket. Native messaging (\\.\pipe\claude-mcp-browser-bridge-<user>) is a separate, secondary transport.
Verified NOT to be the cause — we tested all of these:
| Suspected | Result |
|---|---|
| Extension not installed / not signed in | Installed, signed in, from_webstore: true, no disable_reasons |
| Chrome side panel not open | Open, no effect |
| Missing native-host manifest | Created it → host launched → still "not connected" |
| Chrome enterprise policies | None present in HKLM / HKCU / WOW6432Node |
| Chrome restart / machine reboot | No effect |
| Claude Code version skew (2.1.255 vs 2.1.257) | Fresh 2.1.255 works fine |
| Stale in-memory token in a long-lived process | A process started 42 min after re-auth failed identically — the staleness was on disk |
| ant-device-registry.json frozen weeks earlier | Browser tools worked for a week after that date |
| Filesystem corruption (boot chkdsk) | 0 bad file records, nothing repaired |
Discriminator that finally isolated it: within the same minute, on the same machine, same extension, same account, same binary version — a headless claude.exe --chrome -p … returned the browser while the Desktop-hosted session returned "not connected".
---
Environment
- Windows 11 Pro 10.0.26200
- Chrome 152.0.7977.65, extension
fcoeoabgfenejglbffodgkkbkcdhcgfnv1.0.90 - Claude Desktop 1.40609.1.0 (MSIX,
SignatureKind: Developer) - Claude Code bundled in Desktop 2.1.255; standalone CLI 2.1.257
Summary of asks
- Clear the OAuth token cache on
401, not only on403. - Make the browser-tool error distinguish a local connect/auth failure from an empty roster, and stop attributing it to the user's extension.
- Have Desktop honour
claudeInChromeDefaultEnabled(or pass--chrome). - Ship the missing
com.anthropic.claude_browser_extension.json.
Related issues
All describe the same symptom; all closed without a working resolution:
#58009, #58968, #72606, #76347, #79228, #29528, #71058