anomalyco / anomalyco/browser-control
CDP detaches after ~5-15s on heavy SPAs: banner auto-closes, 'Execution context destroyed' loop, session bound to dead target
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 407
- Forks
- 20
- Avg merge
- 9h 22m
- Merged PRs (30d)
- 33
Description
Environment
- browser-control CLI/relay: 0.5.1 (build
2026-08-23T23:42:36.863Z) - Extension: 0.0.24, protocol v2 (compatible)
- Browser: Chrome/Edge 151.0.0.0, Linux x86_64 (X11)
browser-control doctor: all checks ok
Summary
Automating a heavy SPA (LinkedIn company-page admin editor) fails reproducibly: ~5–15s after navigation the CDP session drops — the Chromium "started debugging this browser" banner closes by itself, every page.evaluate then fails with Execution context was destroyed, most likely because of a navigation, and the relay declares the page unresponsive and recreates it. The session is then bound to the dead target, and subsequent executes fail with Debugger is not attached to the tab with id: <id> until the page is manually re-created. URL never changes during the loop, so it is the target site tearing down/reloading the renderer (presumably CDP detection) — but Browser Control's reaction to it (detach + recreate + stale binding) turns one bad page into a wedged session.
Repro
browser-control execute 'await page.goto("https://www.linkedin.com/company/<id>/admin/edit/?editPageActiveTab=info", { waitUntil: "commit" })'- Wait 5–15s (authenticated SPA, heavy).
- Any
page.evaluate/snapshotnow fails withExecution context was destroyed.... - Next execute reports
The session default page was closed; created a new page+...was unresponsive; created a new page; new page isabout:blank. - Re-
goto→ sometimes works once, then loops back to step 3.
Polling page.url() every 2.5s for 15s showed the same URL throughout while every evaluate context died — i.e. same-URL reload loop, not a real navigation.
Actual behavior
- Debugger banner auto-closes a few seconds after attach (user-observed); CDP detaches mid-operation.
- Relay recreates the page but the session keeps referencing the old target id →
Protocol error (Page.navigate): Debugger is not attached to the tab with id: 97354. - Target selection flaps:
status --jsonlists the user-attached target (activeTargets: 1), but an immediately-followingexecute --target-url linkedinreturns "No existing attached page URL includes linkedin".
Expected behavior
- On renderer teardown/reload: re-attach CDP to the same tab (the tab still exists) instead of recreating the page and orphaning the session binding.
- Stale binding (
Debugger is not attached to the tab with id) should self-heal: re-resolve the session's default target by URL/id before failing. - Target announce → select consistency: a target listed by
statusshould be selectable by--target-urlin the immediately following command.
Workarounds tried
- Retry with longer settle (10–12s),
waitUntil: commit/domcontentloaded, atomic goto+wait+act in one execute — works once occasionally, then degrades again. - User-attached tab via toolbar: attach flaps the same way (listed in
status, unselectable seconds later). - Fresh session + fresh relay-created page: same loop on this site. Regular/light pages work fine.
Notes
- Happy to capture
BROWSER_CONTROL_DEBUG=1traces or a recording on request (will omit all page content). - Repro URL is a LinkedIn admin page (auth-gated); happy to test against any provided heavy-SPA test page instead.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the CDP detach and target lifecycle paths used by execute, status --json, and --target-url, then reproduce the same-URL renderer teardown on a heavy SPA. Done means the existing tab is reattached without orphaning the session, stale target bindings recover, and a target reported by status remains selectable immediately afterward.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, devtools, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100