Silent tab drift on CDP-attached Edge: set viewport returns OK without applying, commands run in an unrelated tab
Driving Edge over CDP from a long-lived scripted session, commands silently detach from the intended tab. Three symptoms, same session:
set viewport 375 667prints✓ Done, but the nexteval "window.innerWidth"returns1912(the real window size). Re-issuing later works. No error, exit 0.open <url>+waitreturn success, theneval "location.pathname"reads an unrelated tab (in my runs, one of the human's tabs: their x.com tab,/home,/hub, …). Measurements/screenshots for the wrong page are silently produced.- A tab stops responding (
✗ Cannot switch to tab t14: tab is not responding and did not recover after activation),tab closestill works, and subsequent commands continue on another tab with exit 0. ~13 extrat<n>tabs at my localhost URLs appeared during the runs although my scripts only issuedopenon one tab.
Environment
agent-browser 0.38.0 (npm global, daemon agent-browser-linux-x64) · Node v26.8.2 · Pop!_OS 24.04, kernel 7.1.5 · Microsoft Edge Flatpak com.microsoft.Edge 153.0.4234.32-1 · CDP ws://127.0.0.1:9222/devtools/browser/<uuid> built from DevToolsActivePort · session assistant, namespace agent-browser-skill · agent-browser doctor: 10 pass / 0 warn / 0 fail · daemon (pid 31694) alive across every failure.
Scale: ~56 navigations in one session (28 states × open + set viewport + theme + wait + screenshot --full). Loops of 30–40 lighter iterations did not reproduce it; it needs the long-lived session.
What is happening (0.38.0)
The session persists its bound target in /run/user/1000/agent-browser/namespaces/agent-browser-skill/run/assistant.target:
{"targetId":"033B991C…","url":"https://x.com/…","pinned":false}
tab --help documents the behavior: the session remembers its active tab (bound by CDP target id), and "With --pin-tab, commands fail with a tab_gone error instead of falling back to another tab when the bound tab is closed." So the binding works; the silent part is the unpinned fallback — when the bound tab is closed or unresponsive, the next command re-binds to the most recently active page (often a human tab) and runs there with exit 0.
Repro (fallback → unrelated tab, exit 0)
export AGENT_BROWSER_SESSION=repro
agent-browser tab new --label repro http://localhost:3001/ # binds repro.target to the new tab
agent-browser get url # -> http://localhost:3001/
agent-browser tab close repro # bound target is gone
agent-browser get url # actual: another tab's URL, exit 0
cat /run/user/$UID/agent-browser/namespaces/<ns>/run/repro.target # rebound, pinned:false
The same sequence with the pin is loud (0.38.0):
$ AGENT_BROWSER_PIN_TAB=1 agent-browser tab new --label repro http://localhost:3001/ \
&& agent-browser get url && agent-browser tab close repro && agent-browser get url; echo exit=$?
✗ tab_gone: bound tab is gone (target 9A918B23…, last url http://localhost:3001/). Run `agent-browser tab new <url>` to bind a new tab, or `agent-browser tab list` to pick an existing one
exit=1
Additional diagnostics
- Read-only dump via Node's built-in WebSocket against the browser endpoint —
Browser.getVersion:Edg/153.0.4234.32, protocol 1.3;Target.getTargets: 54 targets, 14 page targets, every oneattached: true(the CLI holds a CDP session on all tabs, including the human's). tab list --jsonalready exposesdata.tabs[].targetIdanddata.lifecycle(reused: truethroughout); CDP target ids stay stable across daemon restarts and are accepted as tab refs.
Impact
Automation that trusts exit codes silently measures/screenshots the wrong page (I hit it twice; I now assert path, viewport and theme before and after every command and cross-check screenshot dimensions against documentElement.scrollWidth). In a session bound to a human tab, the next open navigates the human's tab.
Suggested fixes (any of these unblocks scripted use)
- Warn on stderr or fail when the unpinned fallback re-binds to a different target.
- Make
set viewportverify the override took effect (or verifyinnerWidthon the next command). - If
opencreates a new tab as a fallback for unresponsive targets, document + warn; if not, that's a separate bug worth its own report. - Consider pinning by default for scripted sessions (or recommending
AGENT_BROWSER_PIN_TAB=1in the docs/skill).
Source: vercel-labs/agent-browser