FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(browser): preserve session after tool timeout by MagMueller · Pull Request #136 · browser-use/browsercode · GitHub

fix(browser): preserve session after tool timeout - #136

Merged
MagMueller merged 9 commits into
mainfrom
timeout-recovery
Aug 3, 2026
Merged

MagMueller merged 9 commits into
mainfrom
timeout-recovery

Conversation

MagMueller commented Aug 2, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Summary

  • keep the underlying CDP connection and target attachment alive when browser_execute times out
  • scope each snippet so its orphaned timers, event callbacks, and result callbacks cannot issue later browser commands
  • let the next tool call continue with the same session, tabs, and active target
  • update the existing timeout rule and add one concise fact about new tabs being separate page targets
  • leave ordinary socket-disconnect behavior unchanged

Why

JavaScript promises cannot be preemptively cancelled. Retiring the complete CDP transport prevents late commands, but also destroys browser context. A per-call async execution scope blocks future browser effects from the timed-out invocation without reconnecting or re-enumerating targets.

The required browser skill changes only two narrow cases: after a timeout it says the existing session is preserved, and when a new tab opens it explains that the active attachment remains on the old page until the intended type: "page" target is selected. Other navigation and waiting guidance is unchanged.

Testing

  • targeted browser timeout/session regressions: 25 passed, 6 environment-dependent skipped
  • exact in-flight CDP regression: the delayed command resolves after the tool deadline, its orphaned follow-up is rejected, and the next invocation succeeds over the same socket and target
  • bun run typecheck in packages/bcode-browser
  • repository pre-push typecheck (17 packages)
  • GitHub typecheck, security scan, and automated review
  • isolated live-browser tasks completed successfully after real page-target stalls; the agent retained control and chose whether to probe or attach a fresh target

cubic-dev-ai Bot left a comment
edited
Loading

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

1 issue found across 3 files

Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/bcode-browser/src/browser-execute.ts">

<violation number="1" location="packages/bcode-browser/src/browser-execute.ts:312">
P2: When a timeout recovery cannot find the preserved page target (and there is no fallback page target either), this branch throws and leaves `v4TimeoutRecovery[sessionID]` set. On every later `browser_execute` for the same session, `ensureCloudConnected` re-enters the recovery path (`v4Bootstrapped.has(sessionID) && !recoveryState` is false), skips the already-open connect, hits `getTargets`, finds no page, and throws the same error again — and because `ensureCloudConnected` runs before the snippet is executed, the agent can never run a snippet to open a new tab or reconnect manually. The sessionID is effectively permanently stuck until a page target happens to appear in that browser. Consider clearing the recovery entry on this path (e.g. `v4TimeoutRecovery.delete(sessionID)` before throwing) so a subsequent snippet can run and let the agent reconnect explicitly, or otherwise provide a way out of the recovery state.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

const page = targets.find((target) => target.targetId === recoveryState?.targetId)
?? targets.find((target) => target.type === "page" && !target.url.startsWith("chrome://"))
if (recoveryState && !page) {
throw new Error("No page target available after browser_execute timeout")

cubic-dev-ai Bot Aug 2, 2026
edited
Loading

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

P2: When a timeout recovery cannot find the preserved page target (and there is no fallback page target either), this branch throws and leaves v4TimeoutRecovery[sessionID] set. On every later browser_execute for the same session, ensureCloudConnected re-enters the recovery path (v4Bootstrapped.has(sessionID) && !recoveryState is false), skips the already-open connect, hits getTargets, finds no page, and throws the same error again — and because ensureCloudConnected runs before the snippet is executed, the agent can never run a snippet to open a new tab or reconnect manually. The sessionID is effectively permanently stuck until a page target happens to appear in that browser. Consider clearing the recovery entry on this path (e.g. v4TimeoutRecovery.delete(sessionID) before throwing) so a subsequent snippet can run and let the agent reconnect explicitly, or otherwise provide a way out of the recovery state.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/bcode-browser/src/browser-execute.ts, line 312:

<comment>When a timeout recovery cannot find the preserved page target (and there is no fallback page target either), this branch throws and leaves `v4TimeoutRecovery[sessionID]` set. On every later `browser_execute` for the same session, `ensureCloudConnected` re-enters the recovery path (`v4Bootstrapped.has(sessionID) && !recoveryState` is false), skips the already-open connect, hits `getTargets`, finds no page, and throws the same error again — and because `ensureCloudConnected` runs before the snippet is executed, the agent can never run a snippet to open a new tab or reconnect manually. The sessionID is effectively permanently stuck until a page target happens to appear in that browser. Consider clearing the recovery entry on this path (e.g. `v4TimeoutRecovery.delete(sessionID)` before throwing) so a subsequent snippet can run and let the agent reconnect explicitly, or otherwise provide a way out of the recovery state.</comment>

<file context>
@@ -286,27 +294,33 @@ export const make = Effect.fn("BrowserExecute.make")(function* (dataDir: string)
+    const page = targets.find((target) => target.targetId === recoveryState?.targetId)
+      ?? targets.find((target) => target.type === "page" && !target.url.startsWith("chrome://"))
+    if (recoveryState && !page) {
+      throw new Error("No page target available after browser_execute timeout")
+    }
     if (page) await session.use(page.targetId)
</file context>

MagMueller Aug 2, 2026
edited
Loading

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Superseded by the latest revision: the recovery map and target lookup were removed entirely. The next invocation continues on the existing Session without a pre-snippet recovery path.

MagMueller changed the title fix(browser): reconnect after tool timeout fix(browser): preserve session after tool timeout Aug 2, 2026
MagMueller force-pushed the timeout-recovery branch 4 times, most recently from e108833 to d7f3e80 Compare August 2, 2026 16:31

cubic-dev-ai Bot left a comment
edited
Loading

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

All reported issues were addressed across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

MagMueller merged commit 7708a57 into main Aug 3, 2026
3 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant


Back | FazBrowse Home | New Git URL