Skip to content

fix(browser): cancel Chrome MCP requests on crash#101454

Merged
steipete merged 2 commits into
mainfrom
codex/chrome-mcp-crash-cancel
Jul 7, 2026
Merged

fix(browser): cancel Chrome MCP requests on crash#101454
steipete merged 2 commits into
mainfrom
codex/chrome-mcp-crash-cancel

Conversation

@steipete

@steipete steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Closes #101070.

Chrome MCP existing-session actions could outlive the browser request that started them. evaluate, coordinate clicks, wait-loop sleeps, navigation probes, tab discovery, snapshots, uploads, and dialog hooks did not all share the route abort signal and action timeout. A target Chrome crash could therefore leave an agent turn waiting until a deeper default timeout, while OpenClaw's outer Promise.race returned without cancelling the MCP SDK's correlated request.

The report's “indefinite” wording is not universal: @modelcontextprotocol/sdk 1.29.0 has a 60-second default request timeout and rejects in-flight requests when its transport closes. The real OpenClaw gap was that target-browser failure can leave the MCP subprocess alive, and several route paths neither supplied the request signal nor an explicit action budget.

Why This Change Was Made

  • Give timeout and abort ownership to the MCP SDK through RequestOptions.timeout and RequestOptions.signal. The SDK then removes its correlation handler instead of leaving the underlying request pending behind an outer race.
  • Carry one route budget through every Chrome MCP existing-session action, tab discovery, snapshot operation, upload/dialog hook, wait sleep, and post-interaction navigation probe.
  • Evict the failed cached session so the next browser request creates a fresh connection.
  • Keep labeled-screenshot overlay cleanup independent from the cancelled route signal so cancellation cannot leave injected labels in the user's tab.
  • Refactor repeated target/profile/timeout plumbing into one canonical operation shape. Production code is net smaller despite covering the full route surface.

No config, protocol, provider, permission, or browser feature is removed or added.

User Impact

When attached Chrome dies or a browser request is cancelled, the agent now reaches a bounded terminal error and can reconnect on a later request instead of retaining a dead Chrome MCP request. Existing-session clicks, keyboard input, evaluation, waits, snapshots, screenshots, uploads, and dialog hooks remain available.

Evidence

Remote provider: Blacksmith Testbox, lease tbx_01kwxpxmb3x1g1prnaa9cs4230 (silver-prawn).

  • pnpm test extensions/browser/src/browser/chrome-mcp.test.ts extensions/browser/src/browser/routes/agent.act.existing-session-navigation-guard.test.ts extensions/browser/src/browser/server-context.selection.test.ts — 74 passed.
  • pnpm test extensions/browser/src/browser/routes/agent.existing-session.test.ts extensions/browser/src/browser/routes/dispatcher.abort.test.ts extensions/browser/src/browser/routes/agent.snapshot.test.ts extensions/browser/src/browser/routes/agent.snapshot.timeout.test.ts extensions/browser/src/browser/server-context.existing-session.test.ts — 33 passed.
  • pnpm check:changed -- <12 touched browser files> — production/test typechecks, extension lint, repository guards, and import-cycle checks passed.
  • Fresh Codex autoreview (gpt-5.5, high) found one cleanup issue; fixed with an independent overlay-cleanup signal and a regression assertion. The rerun reported no actionable findings.

Focused regressions prove that the SDK receives the timeout/signal, a stuck evaluate cancels and reconnects, wait sleeps abort, coordinate/probe calls share the route budget, initial tab discovery receives it, and label cleanup does not reuse the route signal.

Live Dev Gateway + real OpenAI agent + real target-Chrome crash proof is still pending. This PR does not claim that proof yet and should not land until it is added in a follow-up comment.

@openclaw-barnacle openclaw-barnacle Bot added size: L maintainer Maintainer-authored PR labels Jul 7, 2026
@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 7, 2026, 3:49 AM ET / 07:49 UTC.

Summary
The PR threads route abort signals and action timeouts through Chrome MCP existing-session tool calls, tab discovery, snapshots, hooks, and wait sleeps, adds regression coverage, and adds one CHANGELOG entry.

PR surface: Source -66, Tests +155, Docs +1. Total +90 across 13 files.

Reproducibility: yes. for a source-level reproduction path: current main has Chrome MCP actions and wait paths without SDK-owned timeout/signal propagation. No live paused-breakpoint or target-Chrome crash run was provided or reproduced in this review.

Review metrics: 1 noteworthy metric.

  • Release-owned changelog edits: 1 added entry. CHANGELOG.md is release-owned, so this hand edit should be removed before ordinary PR merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #101070
Summary: This PR is the current candidate fix for the open Chrome MCP target-browser-crash dangling-promise issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🐚 platinum hermit
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted live Dev Gateway/OpenAI-agent proof showing a target Chrome crash aborts the request and the next browser request reconnects.
  • Remove the hand-edited CHANGELOG.md entry and keep that release-note context in the PR body or squash message.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body provides focused Testbox/unit and check evidence but explicitly says live Dev Gateway plus real target-Chrome crash proof is still pending; add redacted logs, terminal output, or an artifact, then update the PR body to trigger a fresh review or ask a maintainer for @clawsweeper re-review.

Risk before merge

  • [P1] Live Dev Gateway plus real OpenAI agent proof for an actual target-Chrome crash is still missing, and the PR body explicitly says it should not land until that proof is added.
  • [P2] The diff expands abort/timeout-triggered Chrome MCP session eviction across more existing-session actions, so maintainers need confidence that request cancellation does not unexpectedly disrupt healthy concurrent browser automation.

Maintainer options:

  1. Require live crash and reconnect proof (recommended)
    Ask for redacted terminal/log or artifact proof from a real Dev Gateway/OpenAI-agent session where target Chrome crashes, the request terminates, and the next request reconnects.
  2. Accept focused-test coverage only
    Maintainers can intentionally merge with unit/Testbox evidence only, while owning the remaining browser-session-state uncertainty.
  3. Pause until proof is practical
    If live proof cannot be produced soon, keep the PR open rather than landing a session-lifecycle change without end-to-end evidence.

Next step before merge

  • [P1] Human review should wait on real crash-path proof because automation cannot provide the contributor's live Dev Gateway/target-Chrome evidence.

Maintainer decision needed

  • Question: Should this Chrome MCP crash fix wait for live Dev Gateway plus real target-Chrome crash proof before merge, or is the current Testbox/unit evidence enough for this maintainer-labeled PR?
  • Rationale: The code shape and dependency contract look sound, but the PR itself states live crash proof is pending and the changed behavior affects Chrome MCP session cancellation and reconnect semantics.
  • Likely owner: steipete — They introduced Chrome MCP existing-session support, authored this PR, and are the clearest owner for proof sufficiency on this path.
  • Options:
    • Wait for live crash proof (recommended): Require a redacted live run showing the request aborts, the dead MCP session is evicted, and a later browser request reconnects successfully.
    • Accept unit-level proof: Merge with the current focused tests and own the remaining risk that the exact target-crash path behaves differently in a real gateway session.

Security
Cleared: The diff does not add dependencies, lockfile changes, CI/script execution paths, permissions, secrets handling, or downloaded artifacts; it uses the existing MCP SDK request options.

Review findings

  • [P3] Remove the release-owned changelog edit — CHANGELOG.md:24
Review details

Best possible solution:

Keep this PR as the candidate fix, remove the hand-edited changelog entry, add redacted live crash/reconnect proof, and then merge after exact-head checks are green.

Do we have a high-confidence way to reproduce the issue?

Yes for a source-level reproduction path: current main has Chrome MCP actions and wait paths without SDK-owned timeout/signal propagation. No live paused-breakpoint or target-Chrome crash run was provided or reproduced in this review.

Is this the best way to solve the issue?

Yes for the code direction: SDK-owned RequestOptions plus one route budget is the narrow maintainable fix. Merge readiness still depends on live crash proof and removing the release-owned changelog edit.

Full review comments:

  • [P3] Remove the release-owned changelog edit — CHANGELOG.md:24
    CHANGELOG.md is release-owned in this repo; normal PRs should keep release-note context in the PR body or squash message. Please drop this hand-edited unreleased entry so release generation remains the single source of truth.
    Confidence: 0.93

Overall correctness: patch is correct
Overall confidence: 0.82

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against e72dadbb3bb1.

Label changes

Label changes:

  • add P2: This is a normal browser automation reliability fix for a limited Chrome MCP existing-session crash/hang path.
  • add merge-risk: 🚨 session-state: The PR broadens abort/timeout-driven Chrome MCP session eviction across existing-session actions, which can affect browser automation session state if the live path behaves differently than tests.
  • add rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body provides focused Testbox/unit and check evidence but explicitly says live Dev Gateway plus real target-Chrome crash proof is still pending; add redacted logs, terminal output, or an artifact, then update the PR body to trigger a fresh review or ask a maintainer for @clawsweeper re-review.

Label justifications:

  • P2: This is a normal browser automation reliability fix for a limited Chrome MCP existing-session crash/hang path.
  • merge-risk: 🚨 session-state: The PR broadens abort/timeout-driven Chrome MCP session eviction across existing-session actions, which can affect browser automation session state if the live path behaves differently than tests.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body provides focused Testbox/unit and check evidence but explicitly says live Dev Gateway plus real target-Chrome crash proof is still pending; add redacted logs, terminal output, or an artifact, then update the PR body to trigger a fresh review or ask a maintainer for @clawsweeper re-review.
Evidence reviewed

PR surface:

Source -66, Tests +155, Docs +1. Total +90 across 13 files.

View PR surface stats
Area Files Added Removed Net
Source 8 307 373 -66
Tests 4 178 23 +155
Docs 1 1 0 +1
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 13 486 396 +90

What I checked:

  • Repository policy applied: Read the full root AGENTS.md and scoped extensions/AGENTS.md; the review applied the browser plugin boundary, dependency-contract, real-behavior-proof, and release-owned changelog guidance. (AGENTS.md:1, e72dadbb3bb1)
  • Current main still has the source-level gap: Current main races MCP calls outside the SDK request options and several existing-session actions call Chrome MCP helpers without route timeout/signal propagation, matching the linked issue's source-level concern. (extensions/browser/src/browser/chrome-mcp.ts:1234, e72dadbb3bb1)
  • PR centralizes SDK-owned cancellation: The PR passes RequestOptions.timeout/signal into client.callTool and funnels target-scoped helpers through callTargetTool, so SDK request cleanup rather than an outer race owns cancellation. (extensions/browser/src/browser/chrome-mcp.ts:1245, 66e551992588)
  • Route surface now carries one budget: The PR builds one existingSessionCallOptions object from request signal plus action/default timeout and forwards it through action execution, navigation probes, listTabs, wait sleeps, snapshots, screenshots, uploads, and dialog hooks. (extensions/browser/src/browser/routes/agent.act.ts:402, 66e551992588)
  • MCP SDK contract checked: @modelcontextprotocol/sdk 1.29.0 RequestOptions defines signal and timeout, default timeout is 60000ms, request abort removes response/progress handlers and sends cancellation, and transport close rejects response handlers. (extensions/browser/package.json:8, 66e551992588)
  • Regression tests cover the intended plumbing: The PR adds/updates tests for SDK timeout forwarding, abort-signal cancellation and reconnect, coordinate-action budget propagation, abortable wait sleeps, initial tab discovery, and label cleanup signal independence. (extensions/browser/src/browser/chrome-mcp.test.ts:1209, 66e551992588)

Likely related people:

  • steipete: Introduced Chrome MCP existing-session support and authored this PR; also appears in later browser refactors around the same route/runtime surface. (role: feature introducer and recent area contributor; confidence: high; commits: 593964560ba7, 1a4766051847, 808c34b374ed; files: extensions/browser/src/browser/chrome-mcp.ts, extensions/browser/src/browser/routes/agent.act.ts, extensions/browser/src/browser/routes/agent.snapshot.ts)
  • rohitjavvadi: Authored the pending attach abort isolation and Chrome MCP lifecycle hardening commit near the affected session cache and abort paths. (role: recent lifecycle hardening contributor; confidence: high; commits: 3fc485ca92d8; files: extensions/browser/src/browser/chrome-mcp.ts, extensions/browser/src/browser/chrome-mcp.test.ts)
  • masatohoshino: Authored the snapshot timeout propagation work that touched Chrome MCP helper timeout handling and tests adjacent to this PR. (role: adjacent timeout contributor; confidence: medium; commits: 069c7b87eb67; files: extensions/browser/src/browser/chrome-mcp.ts, extensions/browser/src/browser/routes/agent.snapshot.ts, extensions/browser/src/browser/chrome-mcp.test.ts)
  • eleqtrizit: Authored the existing-session navigation guard change in the route surface this PR now threads request budget through. (role: existing-session navigation contributor; confidence: medium; commits: daeb74920d5a; files: extensions/browser/src/browser/routes/agent.act.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 66e5519925

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const readTabs = async (): Promise<BrowserTab[]> => {
try {
const tabs = await listTabs();
const tabs = await listTabs(options);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Thread request budget into empty-tab creation

The new request budget is only forwarded to listTabs here; when both discovery reads succeed with no tabs, openWhenConfirmedEmpty still calls openTab("about:blank") without the same signal/timeout. For Chrome MCP profiles that path goes through openChromeMcpTab/new_page with no SDK RequestOptions, so a crashed or stuck target during first-tab creation ignores the route abort/action timeout and falls back to the SDK default instead of cancelling promptly. Pass the operation options through the openTab dependency as well.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jul 7, 2026
@steipete
steipete force-pushed the codex/chrome-mcp-crash-cancel branch from 66e5519 to 7fd183e Compare July 7, 2026 11:04
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready proof for exact head ddeac879f9d58ea5af0941261341b68a54d7b3e5:

  • 100 focused Browser tests passed on Blacksmith Testbox-through-Crabbox tbx_01kwy411jwmgvgk97n62fwjd15.
  • Exact-head pnpm check:changed passed on the same Testbox in 4m54s.
  • AWS Crabbox cbx_d9f1ede1c74e, run run_e434c1a37f14: started a real Gateway and Chromium existing-session profile, warmed it through an openai/gpt-5.4 agent turn, then killed Chrome during a never-resolving evaluate tool call. The agent reached its terminal crash reply 13,974ms after the kill instead of remaining pending.
  • The same Chrome target was restarted on the same CDP endpoint. A follow-up turn in the same agent session read the page marker successfully through a fresh MCP session; no Gateway restart was needed.
  • Normal and failure branches covered: shared request budget through actions/navigation/snapshots/tab selection, dead-session eviction, restart reconnect, and overlay cleanup detached from an aborted route signal.
  • Fresh Codex autoreview found two stale exact-call test assertions; those were corrected, 100 focused tests reran green, and the follow-up review was clean.

Dependency contract checked directly in @modelcontextprotocol/sdk 1.29.0:

  • dist/esm/client/index.js:490-495: Client.callTool forwards request options to Protocol.request.
  • dist/esm/shared/protocol.js:612-714: request abort deletes handlers, sends cancellation, rejects, and owns the timeout.
  • dist/esm/shared/protocol.d.ts:63-87: signal and timeout are supported request options.

This removes duplicate timeout ownership without relaxing navigation, SSRF, browser-access, or sandbox policy.

@steipete
steipete merged commit 3901094 into main Jul 7, 2026
102 checks passed
@steipete
steipete deleted the codex/chrome-mcp-crash-cancel branch July 7, 2026 11:22
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 8, 2026
* fix(browser): cancel Chrome MCP requests on crash

* test(browser): cover request budget options
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
* fix(browser): cancel Chrome MCP requests on crash

* test(browser): cover request budget options
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer Maintainer-authored PR merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Chrome MCP leaves dangling promises on target browser crash

1 participant