← Back to PRs

#16030: fix(browser): extend single-tab fallback to remote CDP profiles

by lailoo open 2026-02-14 05:58 View on GitHub →
stale size: S experienced-contributor
## Summary Fixes #15989. When a remote CDP connection reconnects (e.g. Browserless session cleanup), the new Chrome process has no previous tabs. If the agent passes a stale `targetId` from the previous session, `ensureTabAvailable()` should fall back to the single available tab — just like it already does for extension driver profiles. ## Root Cause In `server-context.ts`, the single-tab fallback condition only checked `profile.driver === "extension"`, excluding remote CDP profiles (`!profile.cdpIsLoopback`) from the same recovery path. ## Fix Extend the condition to `(profile.driver === "extension" || !profile.cdpIsLoopback)` — one line change. ## E2E Verification (real Chrome + TCP proxy) Verified with a real headless Chrome process and a TCP proxy on the machine's LAN IP to ensure `cdpIsLoopback=false` (the exact code path hit in production with Browserless): 1. Launch Chrome A (`--remote-debugging-port=19222`) 2. TCP proxy on `10.x.x.x:19223` → `127.0.0.1:19222` (non-loopback cdpUrl) 3. Record real tab targetId via CDP `/json/list` 4. Kill Chrome A, launch Chrome B (new process, new tabs, new targetIds) 5. Call `ensureTabAvailable(staleTargetId)` with Chrome A's old targetId ### Before (main) ``` Chrome A real tabs via proxy: ["57B9C779DD39B8CCB2A3C548CEF24CEA"] Chrome B real tabs via proxy: ["4F529C579FA3A76634F5ABF9113FF120"] ❌ FAIL / BUG CONFIRMED: Error: tab not found ensureTabAvailable threw 'tab not found' instead of falling back to the single available tab. ``` ### After (fix branch) ``` Chrome A real tabs via proxy: ["4474E24A9856B3C1ED02E7E303E2B760"] Chrome B real tabs via proxy: ["7996E9F42514760A814115A8A3D5C171"] ✅ PASS: Recovered to tab 7996E9F42514760A814115A8A3D5C171 Single-tab fallback worked for remote CDP profile. ``` ## Tests Added 3 regression tests to `server-context.remote-tab-ops.test.ts`: 1. **Stale targetId + single tab → recovers** (the fix) 2. **No tabs available → still throws** `tab not found` 3. **Multiple tabs + stale targetId → still throws** `tab not found` All 190 browser tests pass, lint clean. <!-- greptile_comment --> <h3>Greptile Summary</h3> Extended single-tab fallback recovery to remote CDP profiles (`!profile.cdpIsLoopback`) so stale `targetId` values after reconnection (e.g., Browserless session cleanup) fall back to the single available tab instead of throwing "tab not found", matching the behavior already implemented for extension driver profiles. - Changed condition on line 426 from `profile.driver === "extension"` to `(profile.driver === "extension" || !profile.cdpIsLoopback)` to include remote CDP profiles - This matches the same condition used on line 397 for candidate filtering, ensuring consistent handling across the function - Added 3 comprehensive regression tests covering the fix scenario and edge cases (no tabs, multiple tabs) - The fix maintains existing error behavior when recovery isn't appropriate (zero tabs or multiple tabs with stale targetId) <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk - The change is a minimal one-line condition extension that mirrors an existing pattern in the same function (line 397), ensuring consistency. The fix is thoroughly tested with 3 new regression tests covering the success case and edge cases. The logic follows the established pattern for extension driver profiles and doesn't introduce new code paths, only extends an existing recovery mechanism to remote CDP profiles. - No files require special attention <sub>Last reviewed commit: b803258</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs