#16030: fix(browser): extend single-tab fallback to remote CDP profiles
stale
size: S
experienced-contributor
Cluster:
Browser Enhancements and Fixes
## 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
#16905: fix: prevent excessive Chrome tab creation on startup
by MisterGuy420 · 2026-02-15
80.4%
#20207: fix(browser): use profile driver instead of hardcoded name
by mahsumaktas · 2026-02-18
79.0%
#22952: fix(browser): suggest remote profile when local Chrome is not insta...
by dashed · 2026-02-21
78.0%
#15595: fix(browser): avoid local port conflicts for remote cdp
by TsekaLuk · 2026-02-13
77.5%
#19766: fix: Chrome relay extension auto-reattach after SPA navigation
by nishantkabra77 · 2026-02-18
76.3%
#9020: fix(browser): skip port ownership and WS reachability checks for re...
by yepack · 2026-02-04
75.9%
#13568: Fix browser (OpenClaw-managed) launch fail by binding remote debugg...
by singlag · 2026-02-10
75.8%
#14944: fix(browser): prefer openclaw profile in headless/noSandbox environ...
by BenediktSchackenberg · 2026-02-12
75.7%
#19823: fix(browser): stability improvements for headless Chrome
by Milofax · 2026-02-18
75.6%
#16743: fix: auto-reattach browser relay debugger after navigation
by jg-noncelogic · 2026-02-15
75.1%