[SOLVED] Claude in Chrome "not connected" on Windows: stale oauth:tokenCache causes a 401 loop — fix inside

Status Open
Reported on v2.1.257
Maintainer reply None cached
Activity 0 comments · opened Sep 2, 2026

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/profile every ~30s and received 401.
  • The current version clears the token cache automatically only on 403, not on 401.
  • So it looped indefinitely on a cache it would never invalidate.
  • Fresh, valid credentials in ~/.claude/.credentials.json were 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.exe process spawned by Desktop carries --chrome (verified across all running processes).
  • No --claude-in-chrome-mcp child process exists.
  • The user setting claudeInChromeDefaultEnabled was already true and is never consulted, because De() 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 fcoeoabgfenejglbffodgkkbkcdhcgfn v1.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

  1. Clear the OAuth token cache on 401, not only on 403.
  2. Make the browser-tool error distinguish a local connect/auth failure from an empty roster, and stop attributing it to the user's extension.
  3. Have Desktop honour claudeInChromeDefaultEnabled (or pass --chrome).
  4. 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

View original on GitHub ↗