[BUG] Claude in Chrome v1.0.70: Infinite OAuth retry loop on persistent 403 causes side panel flicker and forced logout

Resolved 💬 13 comments Opened May 8, 2026 by porjarlearnchaiyong-hash Closed May 9, 2026

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?

Title

[BUG] Claude in Chrome v1.0.70: Infinite OAuth retry loop on
persistent 403 causes side panel flicker and forced logout

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet

(related but distinct from #29628, #34176 which involve scope errors
in different flows)

  • [x] This is a single bug report
  • [x] I am using the latest version of Claude in Chrome (v1.0.70)

Summary

The Claude in Chrome side panel flickers periodically (~every 10–20s)
and eventually forces a redirect to login, wiping all conversation
context. Network analysis (HAR) reveals an infinite retry loop: the
extension obtains a fresh OAuth token, attempts to upgrade a WebSocket
to bridge.claudeusercontent.com, receives a non-transient 403 error,
and immediately retries — repeatedly, indefinitely.

The server explicitly marks the error as transient: false, yet the
extension treats it as recoverable and re-attempts on every cycle.

Severity

🔴 High — Active sessions interrupted unpredictably; conversation
history permanently lost; reproduces consistently for affected accounts;
extension is unusable in this state.

Evidence (from HAR capture, 5-minute window)

In a 5-minute capture (17:43:24 → 17:48:25), 116 network requests
were recorded with the following pattern repeating ~25 times:

\\\
loop:
POST https://platform.claude.com/v1/oauth/token → 200 OK
WS wss://bridge.claudeusercontent.com/chrome/<bridge_id>
send: { "type": "connect",
"client_type": "chrome-extension",
"extension_version": "1.0.70",
"os_platform": "Windows",
"device_id": "<uuid>",
"oauth_token": "sk-ant-oat01-..." }
receive: { "type": "error",
"error": "OAuth token forbidden (403) —
missing scope or org access",
"reason": "upstream_403",
"upstream_status": 403,
"transient": false }
WS close
GET /api/oauth/profile → 200 OK
(immediately retry)
\
\\

Key observations:

  • All 25 WebSocket attempts received the identical 403 error
  • Server explicitly sets "transient": false — indicating retry

will not help

  • A new OAuth token is minted every cycle — token rotates each

retry, but every fresh token receives the same 403

  • All HTTP requests return 200 — there are no failed REST calls;

the failure is exclusively at the WebSocket layer

  • The OAuth profile endpoint reports the user is authenticated

successfully, yet the bridge rejects the same identity

Suspected Root Cause

Two overlapping issues:

  1. Server-side authorization bug: The OAuth token issued to the

user is missing the scope or org access required by
bridge.claudeusercontent.com. This happens immediately after
login — never works for this account. Possibly related to scope
issues in #29628 and #34176.

  1. Client-side retry-loop bug: The extension does not honor the

server's transient: false flag and retries indefinitely. There
appears to be no exponential backoff or retry cap. This turns a
single auth misconfiguration into a continuous flicker/logout
loop that destroys user state.

The client behavior is independently a bug — even when the underlying
auth issue is fixed, the extension should not retry non-transient
errors aggressively, and should not destroy user-visible state on
each retry.

Steps to Reproduce

  1. Install Claude in Chrome v1.0.70 (ID: fcoeoabgfenejglbffodgkkbkcdhcgfn)
  2. Log in with affected account [details available privately if needed]
  3. Open the side panel, start a conversation
  4. Within ~10–20 seconds: side panel flickers
  5. After several flicker cycles: forced redirect to login
  6. Conversation context is lost
  7. Re-login produces the same loop

Expected Behavior

  • WebSocket bridge accepts the OAuth token issued to a logged-in user

(server-side fix), OR clearly surfaces the actionable error to the
user (e.g., "Your account does not have access to Claude in Chrome —
contact your admin")

  • On transient: false errors, the client stops retrying and shows an

actionable error UI instead of looping

  • Conversation state is preserved across transient WebSocket reconnects

Actual Behavior

  • WebSocket bridge returns persistent 403 immediately on every connect
  • Client retries indefinitely, treating non-transient error as transient
  • Each retry cycle re-renders the side panel (visible flicker)
  • After enough failures, user is logged out and conversation is wiped

Environment

  • Extension version: 1.0.70
  • Extension ID: fcoeoabgfenejglbffodgkkbkcdhcgfn
  • OS: Windows (per WebSocket payload os_platform: "Windows")
  • Chrome version: [TODO — chrome://version]
  • Account type: [TODO — Pro / Team / Enterprise / Free]
  • Org membership: [TODO — relevant if "missing org access" applies]

Tangentially related observations (likely not root cause)

While investigating, the following were also noted but appear unrelated
to the flicker/logout loop:

  • CSP violations on options.html#options:8 for inline scripts

and a third-party Segment/Amplitude CDN load
(cdn.segment.com/.../amplitude-plugins/...). These are Manifest V3
compliance issues but the side panel and service worker continue
functioning despite them.

  • Service worker is healthy during the loop:

Installation: ACTIVATED, Running: RUNNING, Version ID: 76
(per chrome://serviceworker-internals). The service worker
console log is empty.

  • Build artifact name service-worker.ts-gaAAsstG.js retains

the .ts extension before the content hash — minor, but unusual
for a production build.

Suggested Triage

  1. Investigate why bridge service rejects OAuth tokens for this account

with missing scope or org access — coordinate with auth team

  1. Add client-side handling for transient: false errors: stop

retrying, show actionable error UI

  1. Add exponential backoff and retry cap to WebSocket reconnect logic

regardless of error type

  1. Decouple side panel UI state from WebSocket connection lifecycle so

transient reconnects do not visibly re-render or clear conversations

Attachments (please request privately — contain credentials)

  • HAR file with full WebSocket payloads (contains rotating OAuth tokens —

do not share publicly)

  • Service worker internals snapshot
  • Screenshots of CSP errors

What Should Happen?

The Claude in Chrome side panel should maintain a stable session
during normal use. Specifically:

  1. The WebSocket bridge at bridge.claudeusercontent.com should accept

the OAuth token issued to a successfully logged-in user. If the
token genuinely lacks required scope or org access, the user should
see a clear, actionable error message (e.g., "Your account does
not have access to Claude in Chrome — please contact your admin")
instead of being silently logged out.

  1. When the server returns an error with "transient": false, the

client should stop retrying and surface the error to the user,
not loop indefinitely.

  1. Conversation context in the side panel should persist across

transient WebSocket reconnects. The UI should not be destroyed
on every reconnect attempt.

  1. Users should not be forcibly redirected to the login screen

without explicit action (logout button, expired session after
long idle, etc.).

Error Messages/Logs

Steps to Reproduce

  1. Install Claude in Chrome v1.0.70 from the Chrome Web Store

(Extension ID: fcoeoabgfenejglbffodgkkbkcdhcgfn)

  1. Log in with an Anthropic account
  2. Open the side panel and start a conversation
  3. Open DevTools on the side panel → Network tab → enable "Preserve log"
  4. Wait 10-20 seconds during normal use

Observed loop (repeats every ~10-20 seconds):
a. POST https://platform.claude.com/v1/oauth/token → 200 OK
(fresh token issued)
b. WebSocket connect to wss://bridge.claudeusercontent.com/chrome/<id>
Sends: { "type": "connect", "extension_version": "1.0.70",
"oauth_token": "sk-ant-oat01-..." }
Receives: { "type": "error",
"error": "OAuth token forbidden (403) —
missing scope or org access",
"reason": "upstream_403",
"upstream_status": 403,
"transient": false }
c. WebSocket closes
d. GET /api/oauth/profile → 200 OK
e. Side panel flickers (visible re-render)
f. Loop restarts

After enough cycles: side panel forcibly redirects to login screen,
all conversation context is permanently lost. Re-login reproduces
the same loop.

In a 5-minute capture, this loop repeated 25 times with 116 total
network requests. Every WebSocket attempt received the identical
non-transient 403, but a NEW oauth token was minted each cycle
(token rotates every retry, all tokens get the same 403).

Additional context:

  • Service worker remains healthy throughout (status: ACTIVATED +

RUNNING, console log empty per chrome://serviceworker-internals)

  • All HTTP REST calls return 200; failure is exclusively at the

WebSocket layer

  • HAR file with full payloads available on request

(contains rotating OAuth tokens, cannot be shared publicly)

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

N/A — this is a Claude in Chrome extension bug, not Claude Code CLI. Claude in Chrome extension version: 1.0.70 Extension ID: fcoeoabgfenejglbffodgkkbkcdhcgfn

Platform

Other

Operating System

Windows

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗

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