Skip to content

Chrome extension relay: frequent disconnects require manual re-attach (fixable in background.js) #15099

@codexGW

Description

@codexGW

GitHub Issue Draft: Chrome Extension Relay Disconnects

Repo: https://github.com/openclaw/openclaw
File: Post as a new issue


Title

Chrome extension relay: frequent disconnects require manual re-attach (fixable in background.js)

Labels

bug, browser, extension

Body

Problem

The Chrome extension relay (background.js) disconnects frequently during normal use. The user attaches a tab via the toolbar button, uses it successfully, then minutes later the agent gets "tab not found (no attached Chrome tabs for profile 'chrome')." The user must manually re-click the toolbar icon to reattach.

This happens mid-workflow — e.g., agent navigates to site A successfully, then a few minutes later tries to navigate to site B and the connection is gone.

Environment

  • OpenClaw 2026.2.9
  • Brave Browser (Chromium-based, supports chrome.debugger)
  • macOS 15 (Apple Silicon)
  • Extension loaded unpacked via openclaw browser extension install

Root Cause Analysis

After reviewing background.js, three issues cause the disconnects:

1. WebSocket drop nukes all debugger sessions (lines ~105-120)

onRelayClosed() calls chrome.debugger.detach() on every attached tab and clears all state when the relay WebSocket drops. Any transient WebSocket hiccup (network blip, service worker restart) destroys all debugger sessions even though the debugger attachment itself was fine.

// Current behavior — relay drop = detach everything
function onRelayClosed(reason) {
  relayWs = null
  // ...
  for (const tabId of tabs.keys()) {
    void chrome.debugger.detach({ tabId }).catch(() => {})  // ← unnecessary
  }
  tabs.clear()
}

Fix: Don't detach debugger on relay loss. Keep debugger attached, mark relay as disconnected, reconnect WS, then re-announce existing sessions.

2. No WebSocket auto-reconnect

ws.onclose and ws.onerror only call onRelayClosed() — no reconnect attempt. The connection stays dead until the user manually clicks the toolbar icon.

Fix: Add exponential backoff reconnect in onRelayClosed():

function onRelayClosed(reason) {
  relayWs = null
  // DON'T detach debugger sessions
  // Schedule reconnect
  scheduleReconnect()
}

let reconnectAttempt = 0
function scheduleReconnect() {
  const delay = Math.min(1000 * 2 ** reconnectAttempt, 30000) + Math.random() * 1000
  reconnectAttempt++
  setTimeout(async () => {
    try {
      await ensureRelayConnection()
      reconnectAttempt = 0
      // Re-announce all still-attached tabs
      for (const [tabId, tab] of tabs.entries()) {
        if (tab.state === 'connected') {
          // Send attachedToTarget events for each tab
        }
      }
    } catch {
      scheduleReconnect()
    }
  }, delay)
}

3. MV3 service worker state loss (lines ~19-24)

All tab/session state is in-memory Maps. When Chrome kills the MV3 service worker (~30s idle without activity), state is lost. The debugger may still be attached at the Chrome level, but the extension forgot about it.

Note: Since Chrome 118, active chrome.debugger sessions keep the worker alive, and since Chrome 116, WebSocket traffic resets the idle timer. But if both are briefly inactive, the worker can still die.

Fix: Persist minimal state (tabId, sessionId, targetId) to chrome.storage.session. On worker startup, rehydrate and validate with chrome.tabs.get().

4. No tab lifecycle cleanup (minor)

No chrome.tabs.onRemoved or chrome.tabs.onReplaced listeners. Closed/replaced tabs leave stale entries in the Maps, which can cause "No attached tab" errors.

Fix: Add listeners to clean up state when tabs close or get replaced (prerender swap).

Impact

This is the biggest friction point when using the Chrome relay. Every disconnect requires physical user intervention (clicking the toolbar button), which breaks automated workflows and makes the relay unreliable for anything beyond single-shot use.

Suggested Priority

The fixes are straightforward and contained within background.js. The most impactful single change is #1 (don't detach on WS drop) combined with #2 (auto-reconnect), which would eliminate most user-facing disconnects.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions