-
-
Notifications
You must be signed in to change notification settings - Fork 39.9k
Description
Problem
When using a remote CDP profile (e.g., Browserless), ensureTabAvailable() throws "tab not found" after the persistent Playwright connection drops and reconnects.
Reproduction scenario
- OpenClaw connects to a remote Browserless instance via
connectOverCDP()→ Chrome fix: add @lid format support and allowFrom wildcard handling #1 is created - A tab is opened →
lastTargetId = "abc123"is stored in profile state - The persistent CDP WebSocket drops (network issue, Browserless session cleanup, etc.)
onDisconnectedfires →cached = null→ Chrome fix: add @lid format support and allowFrom wildcard handling #1 is killed by Browserless- Next browser request →
connectBrowser()→ freshconnectOverCDP()→ Chrome Login fails with 'WebSocket Error (socket hang up)' ECONNRESET #2 (new process, no previous tabs) - The AI agent passes
targetId = "abc123"from the previous session resolveById("abc123")returnsnull— Chrome Login fails with 'WebSocket Error (socket hang up)' ECONNRESET #2 has no tab with that ID- Error: "tab not found"
Root cause
In server-context.ts, ensureTabAvailable() has a graceful fallback for the extension driver when a stale targetId doesn't match and only one tab is available:
let chosen = targetId ? resolveById(targetId) : pickDefault();
if (!chosen && profile.driver === "extension" && candidates.length === 1) {
// Recover by using the single attached tab
chosen = candidates[0] ?? null;
}This fallback does not apply to remote CDP profiles (!profile.cdpIsLoopback), even though the same stale-targetId scenario is common with remote browsers like Browserless where each new WebSocket connection spawns a fresh Chrome process.
Proposed fix
Extend the single-tab fallback to also cover remote CDP profiles:
if (!chosen && (profile.driver === "extension" || !profile.cdpIsLoopback) && candidates.length === 1) {
chosen = candidates[0] ?? null;
}The reasoning is the same as for extension relay: if an agent passes a stale/foreign targetId but we only have a single page available, recover by using that page instead of failing hard.
Environment
- Remote CDP via Browserless v2 (Chrome image) on Fly.io
- Persistent
connectOverCDP()connection withTIMEOUT=-1 - Connection drops trigger fresh Chrome creation (no session persistence in Browserless v2 + Playwright)
Related issues
- [Bug]: Isolated OpenClaw browser (Brave) frequently becomes unreachable during automation (“browser control service timed out”), sometimes leaving CDP port stuck #10994 — AbortSignal fix for stuck CDP connections (helps with reconnection, but doesn't address stale targetId)
- Browser extension relay: tab not found when multiple tabs have same URL #1998 — tab not found with extension relay (same
findPageByTargetIdcode path) - Browser extension relay returns stale tab cache after CDP connections die #6175 — stale tab cache after CDP connections die