Skip to content

fix(tools): Add browser crash detection and automatic session recovery - #2738

Merged
neubig merged 11 commits into
mainfrom
fix/browser-crash-recovery
May 8, 2026
Merged

neubig merged 11 commits into
mainfrom
fix/browser-crash-recovery

Conversation

@VascoSch92

@VascoSch92 VascoSch92 commented Apr 7, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Adds crash detection to BrowserToolExecutor: after 3 consecutive action failures, the browser session is automatically reset (_initialized = False) so the next action re-creates it
  • Uses a shorter timeout (30s instead of 300s) after a failure to avoid long cascading waits against a dead browser
  • Resets the failure counter on success
  • Includes recovery context in error messages so the agent knows the browser was restarted

Previously, when the browser crashed, every subsequent action would block for 300 seconds before timing out, effectively making the agent "stuck". Now the executor detects the pattern and recovers automatically.

Fixes #2412

Test plan

  • 3 new tests: test_issue_2412_consecutive_failures_reset_session, test_issue_2412_success_resets_failure_counter, test_issue_2412_degraded_timeout_after_failure
  • All 59 existing browser unit tests pass
  • Manual test: start a browser task, kill chrome, verify agent recovers

Agent Server images for this PR

• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.13-nodejs22-slim Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:0f1b740-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-0f1b740-python \
  ghcr.io/openhands/agent-server:0f1b740-python

All tags pushed for this build

ghcr.io/openhands/agent-server:0f1b740-golang-amd64
ghcr.io/openhands/agent-server:0f1b740-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:0f1b740-golang-arm64
ghcr.io/openhands/agent-server:0f1b740-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:0f1b740-java-amd64
ghcr.io/openhands/agent-server:0f1b740-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:0f1b740-java-arm64
ghcr.io/openhands/agent-server:0f1b740-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:0f1b740-python-amd64
ghcr.io/openhands/agent-server:0f1b740-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-amd64
ghcr.io/openhands/agent-server:0f1b740-python-arm64
ghcr.io/openhands/agent-server:0f1b740-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-arm64
ghcr.io/openhands/agent-server:0f1b740-golang
ghcr.io/openhands/agent-server:0f1b740-java
ghcr.io/openhands/agent-server:0f1b740-python

About Multi-Architecture Support

  • Each variant tag (e.g., 0f1b740-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 0f1b740-python-amd64) are also available if needed

When the browser crashes, BrowserToolExecutor now detects consecutive
failures and automatically resets the session instead of looping
on the dead connection with 300-second timeouts.

Changes:
- Track consecutive action failures in BrowserToolExecutor
- After 3 consecutive failures, set _initialized=False to trigger
  session re-creation on the next action
- Use a shorter timeout (30s) after a failure to avoid long waits
  against a potentially dead browser
- Reset failure counter on success
- Include recovery context in error messages so the agent knows
  the browser was restarted

Fixes #2412

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Apr 7, 2026 •

Copy link
Copy Markdown
Contributor

Python API breakage checks — ✅ PASSED

Result: ✅ PASSED

Action log

@github-actions

github-actions Bot commented Apr 7, 2026 •

Copy link
Copy Markdown
Contributor

REST API breakage checks (OpenAPI) — ✅ PASSED

Result: ✅ PASSED

Action log

@VascoSch92
VascoSch92 requested a review from all-hands-bot April 7, 2026 10:18

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pragmatic solution to a real problem. The recovery logic is straightforward and well-tested. However, this changes tool execution behavior (timeouts and automatic recovery), which per repo guidelines requires eval verification before approval. Please run lightweight evals to ensure no unexpected benchmark impact.

Comment thread openhands-tools/openhands/tools/browser_use/impl.py Outdated
Comment thread openhands-tools/openhands/tools/browser_use/impl.py
@VascoSch92 VascoSch92 changed the title Add browser crash detection and automatic session recovery fix(tools): Add browser crash detection and automatic session recovery Apr 7, 2026
@github-actions

github-actions Bot commented Apr 7, 2026 •

Copy link
Copy Markdown
Contributor

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-tools/openhands/tools/browser_use
   impl.py27817337%57–61, 63–64, 66, 68, 70–73, 75–76, 78, 80, 87, 105–108, 114–115, 120, 122–124, 126–127, 135–137, 139–143, 148, 199, 204–207, 209, 231–233, 236–238, 240, 253, 290–291, 295, 305, 320–321, 326, 343, 349–350, 355, 360, 366–367, 371–372, 378–379, 387–390, 395–397, 404, 412, 430–431, 433–446, 449–462, 464–465, 471, 476–479, 487, 489, 492–493, 499–500, 505–506, 512–513, 517–518, 522–523, 527, 529–530, 532–535, 538–539, 545, 547, 549, 557–558, 562–563, 568–569, 573–574, 578–579, 584–585, 597–598, 609–610, 614–618, 632–634, 639, 644–645, 655, 661–662
TOTAL240471227048% 

VascoSch92 and others added 3 commits April 7, 2026 12:24
…mport

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Attempt to cleanup the old browser process/session before setting
_initialized=False. Uses a short 5s timeout since the browser may
be crashed or wedged. Failures are caught and logged at debug level
since they're expected when the browser is truly dead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VascoSch92
VascoSch92 requested a review from all-hands-bot April 7, 2026 10:36

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Taste Rating: 🟡 Acceptable - Pragmatic solution to a real problem, but the design conflates browser crashes with legitimate action errors.

Verdict: ❌ Needs eval verification - Per the previous review and repo guidelines, changes to tool execution behavior (timeouts, automatic recovery) require lightweight eval runs before approval. Please run evals to verify no unexpected benchmark impact.

Comment thread openhands-tools/openhands/tools/browser_use/impl.py Outdated
Comment thread openhands-tools/openhands/tools/browser_use/impl.py
Comment thread openhands-tools/openhands/tools/browser_use/impl.py
Comment thread tests/tools/browser_use/test_browser_executor.py
Regular action errors (invalid selector, missing element) are normal
agent mistakes, not browser crashes. Only timeouts indicate a
potentially dead/hung browser and should count toward session reset.

Also makes degraded timeout less aggressive: kicks in after 2+
consecutive timeouts instead of after any single failure.

Adds test for action errors not triggering reset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@VascoSch92
VascoSch92 requested a review from all-hands-bot April 7, 2026 10:49

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Pragmatic solution to a real problem. The recovery logic is straightforward and well-tested. However, this changes tool execution behavior (timeouts and automatic recovery), which per repo guidelines requires eval verification before approval. Please run lightweight evals to ensure no unexpected benchmark impact.

@VascoSch92

Copy link
Copy Markdown
Member Author

@OpenHands fix the pre-commit check

@openhands-ai

openhands-ai Bot commented Apr 7, 2026

Copy link
Copy Markdown

I'm on it! VascoSch92 can track my progress at all-hands.dev

Co-authored-by: openhands <openhands@all-hands.dev>
@openhands-ai

openhands-ai Bot commented Apr 7, 2026

Copy link
Copy Markdown

Summary

I fixed the pre-commit check failure on PR #2738.

What was done:

  • Root cause: The ruff-format pre-commit hook was failing because of a formatting issue in tests/tools/browser_use/test_browser_executor.py
  • Fix applied: Changed a 3-line function call to a single line (line 333) as required by ruff-format:
    # Before
    error_result = BrowserObservation.from_text(
        text="Element not found", is_error=True
    )
    
    # After
    error_result = BrowserObservation.from_text(text="Element not found", is_error=True)
  • Committed and pushed: Commit bf0ed5dd with the fix

Checklist:

@all-hands-bot

This comment was marked as off-topic.

1 similar comment
@all-hands-bot

This comment was marked as off-topic.

xingyaoww commented Apr 21, 2026 •

Copy link
Copy Markdown
Contributor

@OpenHands /codereview /github-pr-review


🤖 This comment was automatically posted by the pr-triage skill (OpenHands) on behalf of a maintainer. See PR #2906 for skill details.

@openhands-ai

openhands-ai Bot commented Apr 21, 2026

Copy link
Copy Markdown

I'm on it! xingyaoww can track my progress at all-hands.dev

@xingyaoww xingyaoww 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.

🟡 Acceptable — Solid, pragmatic fix for a real user-facing problem. The approach is clean: count consecutive timeouts, degrade the timeout to avoid long cascading waits, reset the session after enough evidence of a dead browser. Tests cover the important cases well.

⚠️ Eval risk: This changes browser tool execution behavior (crash recovery, timeout degradation), which could plausibly affect benchmark performance. Flagging for a human maintainer to validate after running lightweight evals.

[RISK ASSESSMENT]

  • [Overall PR] ⚠️ Risk Assessment: 🟡 MEDIUM
  • The crash recovery mechanism changes how the agent experiences browser failures — instead of indefinite 300s timeouts, it now gets faster failure signals and automatic session restarts. This is almost certainly a net positive for agent reliability, but the changed timing/error messages could affect agent decision-making in benchmarks.

VERDICT:
✅ Worth merging pending eval validation.

KEY INSIGHT:
The core mechanism (timeout counter → degraded timeout → session reset) is simple and correct; the main improvement opportunity is eliminating the magic number coupling between the degraded-timeout threshold and MAX_CONSECUTIVE_FAILURES.

This review was generated by an AI assistant (OpenHands) on behalf of xingyaoww.

Comment thread openhands-tools/openhands/tools/browser_use/impl.py
Comment thread openhands-tools/openhands/tools/browser_use/impl.py Outdated
@openhands-ai

openhands-ai Bot commented Apr 21, 2026

Copy link
Copy Markdown

Summary

I completed the requested code review of PR #2738 ("fix(tools): Add browser crash detection and automatic session recovery") and posted it as a GitHub PR review.

What was done:

  1. ✅ Retrieved and analyzed the full PR diff — Examined changes to impl.py (crash detection logic) and test_browser_executor.py / test_browser_initialization.py (new and updated tests).

  2. ✅ Posted a structured code review using the /codereview and /github-pr-review skill guidelines, including:

    • Overall taste rating (🟡 Acceptable)
    • Risk assessment (🟡 MEDIUM)
    • Two inline comments with GitHub suggestion syntax:
      • 🟠 Important: Magic number 2 should be MAX_CONSECUTIVE_FAILURES - 1 to make the coupling explicit
      • 🟡 Suggestion: Missing return type annotation on _handle_timeout_failure
    • Verdict (✅ Worth merging pending eval validation)
  3. ✅ Followed eval-risk policy — Since the PR changes browser tool execution behavior (timeouts, error messages, crash recovery), I used COMMENT instead of APPROVE per the repo's custom codereview guide, flagging it for human maintainer validation after lightweight evals.

  4. ✅ No code changes were made — This was a review-only task, as instructed by the codereview skill ("DO NOT modify the code; only provide specific, actionable feedback").

  5. ✅ AI disclosure included in the review body.

Review posted at: #2738 (review)

@github-actions

Copy link
Copy Markdown
Contributor

📁 PR Artifacts Notice

This PR contains a .pr/ directory with PR-specific documents. This directory will be automatically removed when the PR is approved.

For fork PRs: Manual removal is required before merging.

@VascoSch92

Copy link
Copy Markdown
Member Author

I run an eval of Gaia (only benchmark which is using the Browser tool): https://openhands-eval-monitor.vercel.app/?run=gaia%2Flitellm_proxy-claude-sonnet-4-5-20250929%2F24825062866%2F&days=15

And we have:

So I pushed a testing script in .pr which should trigger the new code.

@VascoSch92
VascoSch92 requested a review from xingyaoww April 23, 2026 09:43
@all-hands-bot

Copy link
Copy Markdown
Collaborator

[Automatic Post]: This PR seems to be currently waiting for review. @xingyaoww, could you please take a look when you have a chance?

@all-hands-bot

Copy link
Copy Markdown
Collaborator

[Automatic Post]: It has been a while since there was any activity on this PR. @VascoSch92, are you still working on it? If so, please go ahead, if not then please request review, close it, or request that someone else follow up.

@all-hands-bot

Copy link
Copy Markdown
Collaborator

[Automatic Post]: This PR seems to be currently waiting for review. @xingyaoww, could you please take a look when you have a chance?

@neubig
neubig enabled auto-merge (squash) May 8, 2026 17:37
@neubig
neubig merged commit 4b7867d into main May 8, 2026
24 of 26 checks passed
@neubig
neubig deleted the fix/browser-crash-recovery branch May 8, 2026 17:44
StressTestor pushed a commit to StressTestor/software-agent-sdk that referenced this pull request Jun 1, 2026
OpenHands#2738)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: openhands <openhands@all-hands.dev>
pengzhang-create pushed a commit to Pyromind-Dynamics/software-agent-sdk that referenced this pull request Aug 13, 2026
OpenHands#2738)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: openhands <openhands@all-hands.dev>
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.

[Bug]: Agent fails to recover from browser crash during long-running tasks

5 participants