-
-
Notifications
You must be signed in to change notification settings - Fork 69.5k
[Bug]: Bugs in Browser Relay Extension : Last-Tab Guard & Rehydration Retry #40037
Description
Bug type
Behavior bug (incorrect output/state without crash)
Summary
Bugs in Browser Relay Extension : Last-Tab Guard & Rehydration Retry
Summary
Two bugs in the Chrome Browser Relay extension (~/.openclaw/browser/chrome-extension/background.js) cause agents to lose browser access, requiring manual user intervention to recover:
- No guard against closing the last tab — agents can kill the entire browser process
- Fragile tab rehydration after MV3 service worker restarts — attached tabs silently disappear
Both are fixable with small changes to background.js.
Bug 1: Closing the last tab kills the browser process
What happens
The Target.closeTarget handler in background.js calls chrome.tabs.remove() without checking whether the tab being closed is the last one. When an agent closes the last open tab, Chromium exits entirely. The CDP endpoint (port 18800) dies, the relay WebSocket drops, and all browser access is lost.
The web-ai-browser skill documents "NEVER close the last open Chrome tab" as a critical rule, but there is no programmatic enforcement — it relies entirely on the AI agent following instructions, which is unreliable.
How to reproduce
- Have a single Chrome tab open and attached to the relay
- Send a
Target.closeTargetCDP command through the relay - Chrome exits — browser process gone, CDP port unresponsive
Current code (vulnerable)
if (method === 'Target.closeTarget') {
const target = typeof params?.targetId === 'string' ? params.targetId : ''
const toClose = target ? getTabByTargetId(target) : tabId
if (!toClose) return { success: false }
try {
await chrome.tabs.remove(toClose)
} catch {
return { success: false }
}
return { success: true }
}Proposed fix
Query all tabs before closing. Refuse if it's the last one:
if (method === 'Target.closeTarget') {
const target = typeof params?.targetId === 'string' ? params.targetId : ''
const toClose = target ? getTabByTargetId(target) : tabId
if (!toClose) return { success: false }
try {
const allTabs = await chrome.tabs.query({})
if (allTabs.length <= 1) {
console.warn('Refusing to close the last tab — this would kill the browser process')
return { success: false, error: 'Cannot close the last tab' }
}
await chrome.tabs.remove(toClose)
} catch {
return { success: false }
}
return { success: true }
}Bug 2: MV3 service worker restart silently drops attached tabs
What happens
Chrome aggressively suspends MV3 extension service workers after ~30 seconds of inactivity. When the service worker restarts, rehydrateState() restores attached tab state from chrome.storage.session and validates each tab by sending Runtime.evaluate({ expression: '1' }).
If the tab is busy at that moment (e.g., ChatGPT running a long computation, page mid-navigation, heavy JS execution), this single validation attempt fails. The tab is then permanently removed from the in-memory tabs Map. From the relay's perspective, the tab no longer exists — even though it's still visually open in Chrome with the content intact.
The user sees the tab is still there, the badge may even still show "ON" briefly, but the relay reports no attached tabs. The only recovery is to manually click the toolbar icon again to re-attach.
How to reproduce
- Attach a tab to the relay (badge shows "ON")
- Navigate to ChatGPT and start a long-running task (e.g., Deep Research, Thinking mode)
- Wait for the MV3 service worker to suspend (~30s of no relay traffic)
- Trigger a service worker restart (e.g., call
browser(action="tabs")) - The tab may silently disappear from the relay's tab list despite still being open
This is intermittent — it depends on tab busyness at the exact moment of rehydration.
Current code (fragile)
// Phase 2: validate asynchronously, remove dead tabs.
for (const entry of entries) {
try {
await chrome.tabs.get(entry.tabId)
await chrome.debugger.sendCommand({ tabId: entry.tabId }, 'Runtime.evaluate', {
expression: '1',
returnByValue: true,
})
} catch {
tabs.delete(entry.tabId)
tabBySession.delete(entry.sessionId)
setBadge(entry.tabId, 'off')
}
}Proposed fix
Retry validation once with a 1-second delay before permanently dropping the tab:
// Phase 2: validate asynchronously, remove dead tabs.
// Retry once — transient failures (tab busy, navigating) are common
// after MV3 service worker restarts and shouldn't permanently drop a tab.
for (const entry of entries) {
let valid = false
for (let attempt = 0; attempt < 2 && !valid; attempt++) {
try {
await chrome.tabs.get(entry.tabId)
await chrome.debugger.sendCommand({ tabId: entry.tabId }, 'Runtime.evaluate', {
expression: '1',
returnByValue: true,
})
valid = true
} catch {
if (attempt === 0) {
await new Promise((r) => setTimeout(r, 1000))
}
}
}
if (!valid) {
tabs.delete(entry.tabId)
tabBySession.delete(entry.sessionId)
setBadge(entry.tabId, 'off')
}
}Further improvement (optional)
Consider also adding a retry to reannounceAttachedTabs() (lines 244–295) which has the same single-attempt validation pattern and the same failure mode after relay reconnects.
Impact
These two bugs together create a frustrating loop for users relying on the web-ai-browser skill:
- Agent runs a long task on ChatGPT → MV3 worker restarts → tab silently dropped (Bug 2)
- Agent can't find attached tab → tries self-recovery → eventually gives up or closes a tab → accidentally closes last tab (Bug 1)
- Browser process dies → user must manually restart Chrome, navigate to the AI site, and re-attach the tab
This defeats the purpose of autonomous browser automation and requires frequent manual intervention.
Environment
- OpenClaw version: 2026.3.7 (42a1394)
- Extension: OpenClaw Browser Relay v0.1.0
- Chrome extension manifest: MV3
- OS: Linux (Ubuntu)
- Browser: Chromium (Playwright-managed,
/home/openclaw/.cache/ms-playwright/chromium-1208/)
Steps to reproduce
Steps are above
Expected behavior
Also described above
Actual behavior
Also described above
OpenClaw version
20260307
Operating system
Ubuntu latest - chrome v145
Install method
No response
Logs, screenshots, and evidence
Described aboveImpact and severity
Affected : browsing capabilities of openclaw
Additional information
No response