Skip to content

Bug: tab <label> onto a Memory-Saver-discarded tab hangs forever in 0.31.1 and stalls the daemon queue (connect is fixed; same root cause as #1036) #1528

Description

@icekinder

Summary

As of 0.31.1, connect 9222 against a browser with Memory-Saver-discarded tabs completes fine (the main path in #1036 — thanks). But switching to a discarded tab via tab <label> still hangs forever, and while it is stuck, every subsequent command (snapshot, eval, tab) queues behind it in the daemon and also hangs. The daemon recovers only after the hung CLI process disconnects.

Environment

  • agent-browser 0.31.1 (npm), macOS arm64 (Darwin 24.6)
  • Google Chrome 149.0.7827.201, --remote-debugging-port=9222, Memory Saver on (default)

Reproduction

# 1. Chrome with several background tabs, idle long enough for Memory Saver
#    to discard some (renderer process killed; CDP target stays listed).
#    Verify a tab is discarded: raw-CDP Page.enable / Runtime.evaluate to its
#    session gets no reply, ever (no error either).

agent-browser connect 9222   # ✅ works in 0.31.1 (used to hang, see #1036)
agent-browser tab            # lists tabs, incl. the discarded one, e.g. t3
agent-browser tab t3         # ❌ hangs forever
# in another shell, while the above is stuck:
agent-browser snapshot -i    # ❌ also hangs (daemon queue stalled)

Kill the hung CLI → daemon recovers, later commands work again.

Root cause

Same as #1036: a discarded tab has no renderer process, so renderer-bound CDP commands (Page.enable, Runtime.evaluate, Page.bringToFront, …) never get a response. The connect attach path got a fix, but the tab-switch path still awaits a renderer-bound call with no timeout.

Verified fix mechanism (no focus steal)

Page.reload is answered by the browser process and respawns a discarded tab's renderer without focusing/activating the tab. Verified: after sending Page.reload to the dead session and waiting ~2s, the renderer responds and the same tab <label> completes instantly. (Target.activateTarget also revives, but visibly steals the active tab — worse for connect-to-user's-browser workflows.)

Suggested: wrap renderer-bound commands in a timeout, and on timeout either auto-revive via Page.reload (maybe behind a flag, since it reloads the page) or fail the command with a clear "tab is discarded" error instead of stalling the daemon queue.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions