You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When N agents share one Chrome over --cdp <port> with unique --session names, sessions hijack each other's tabs (and the user's tabs). The session's "current tab" is an in-memory index inside the daemon; nothing maps a session to a CDP target across daemon restarts or tab removals, so the pointer silently re-resolves to some other tab.
Reproduction
Verified on a live system (v0.28.0; the relevant code is unchanged in 0.31.1). Start one Chrome with --remote-debugging-port=9222, then create 10 named sessions and open a distinct URL in each:
Result: eval location.href returned the SAME url for all 10 sessions, and tab list from different sessions showed the same current-tab marker. Every session ends up driving whatever tab happens to be active.
Root cause
--session isolates the daemon process, not the tab. Two code paths re-resolve the active tab silently:
Daemon (re)attach.discover_and_attach_targets in cli/src/native/browser.rs attaches to all page targets and sets active_page_index = 0. Target.getTargets returns most-recently-active first, so a fresh daemon (idle-timeout shutdown, crash, or the first command of a new session) adopts whatever tab is currently active, typically another agent's tab.
Tab removal fallback.active_page_index_after_removal and the clamp logic in browser.rs silently shift the pointer to a neighboring tab when the current tab is closed by anyone else.
The consequences compound: open <url> navigates the wrong tab in place, and tab close with no ref closes the wrong tab. There is no persisted session to target mapping anywhere; daemon session state is only {session}.{pid,sock,stream,version} in the socket dir. Meanwhile PageInfo already stores target_id per tab, so the raw data exists. Only the binding, its persistence, and the failure semantics are missing.
Related issues
These look like the same defect surfacing in different code paths:
Persist a session to target binding ({session}.target next to the existing per-session files), written when a session creates a tab or explicitly switches, and re-selected by targetId on attach instead of index 0.
Fail loudly instead of falling back: when the bound tab is gone, return a structured tab_gone error (non-zero exit, machine-readable in --json) while keeping tab list / tab new / tab switch working for recovery.
Gate the strict semantics behind an opt-in --pin-tab flag (sticky per session) so existing scripts keep the legacy fallback; the re-attach-by-binding part is a pure bug fix and applies without the flag.
Summary
When N agents share one Chrome over
--cdp <port>with unique--sessionnames, sessions hijack each other's tabs (and the user's tabs). The session's "current tab" is an in-memory index inside the daemon; nothing maps a session to a CDP target across daemon restarts or tab removals, so the pointer silently re-resolves to some other tab.Reproduction
Verified on a live system (v0.28.0; the relevant code is unchanged in 0.31.1). Start one Chrome with
--remote-debugging-port=9222, then create 10 named sessions and open a distinct URL in each:Result:
eval location.hrefreturned the SAME url for all 10 sessions, andtab listfrom different sessions showed the same current-tab marker. Every session ends up driving whatever tab happens to be active.Root cause
--sessionisolates the daemon process, not the tab. Two code paths re-resolve the active tab silently:discover_and_attach_targetsincli/src/native/browser.rsattaches to all page targets and setsactive_page_index = 0.Target.getTargetsreturns most-recently-active first, so a fresh daemon (idle-timeout shutdown, crash, or the first command of a new session) adopts whatever tab is currently active, typically another agent's tab.active_page_index_after_removaland the clamp logic inbrowser.rssilently shift the pointer to a neighboring tab when the current tab is closed by anyone else.The consequences compound:
open <url>navigates the wrong tab in place, andtab closewith no ref closes the wrong tab. There is no persisted session to target mapping anywhere; daemon session state is only{session}.{pid,sock,stream,version}in the socket dir. MeanwhilePageInfoalready storestarget_idper tab, so the raw data exists. Only the binding, its persistence, and the failure semantics are missing.Related issues
These look like the same defect surfacing in different code paths:
--sessioncollisions)tab closeof an earlier tab can silently retarget the active page #1219 (tab close retargets the active page; closed)--profilesessions lose the active page after the first command and fall back toabout:blank#1211 (active page lost, falls back to about:blank)tab list; a fix for this issue naturally implements it)Proposed fix
{session}.targetnext to the existing per-session files), written when a session creates a tab or explicitly switches, and re-selected by targetId on attach instead of index 0.tab_goneerror (non-zero exit, machine-readable in--json) while keepingtab list/tab new/tab switchworking for recovery.--pin-tabflag (sticky per session) so existing scripts keep the legacy fallback; the re-attach-by-binding part is a pure bug fix and applies without the flag.targetIdin the CLI surface (tab list --json, accept target ids as tab refs), which subsumes Feature request: agent-browser tab list --json – include CDP targetId and support tab operations by targetId #1265.I have an implementation of this ready and will open a PR referencing this issue.