NousResearch/hermes-agent

Error handling for browser provider network calls

Cluster 2746 · agent. Data as of

Nothing open on GitHub. Fix merged in #26247 on 15 May 2026. Check it covers your case.

The short answer

0open issues
0open PRs
3items grouped
Known?
Yes. 3 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #26247. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this resolved, deciding PR #26247. That is separate from the fix event.
Still open
Nothing open on GitHub.

A bug report and corresponding fixes addressing unprotected network calls in browser providers that crash when a connection failure occurs. The fix wraps these calls with error handling to prevent crashes.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #26247 fix(tools): wrap browser provider network calls with error handling

    merged to main

    files: tools/browser_providers/browser_use.py, tools/browser_providers/browserbase.py, tools/browser_providers/firecrawl.py

    Show the diff
    • tools/browser_providers/browser_use.py
      @@ -137,12 +137,22 @@ def create_session(self, task_id: str) -> Dict[str, object]:
                   else {}
               )
       
      -        response = requests.post(
      -            f"{config['base_url']}/browsers",
      -            headers=headers,
      -            json=payload,
      -            timeout=30,
      -        )
      +        try:
      +            response = requests.post(
      +                f"{config['base_url']}/browsers",
      +                headers=headers,
      +                json=payload,
      +                timeout=30,
      +            )
      +        except requests.RequestException as exc:
      +            # Managed mode: propagate raw so callers can retry with the
      +            # preserved idempotency key. Direct mode: wrap network failures
      +            # into a clean RuntimeError for end users.
      +            if managed_mode:
      +                raise
      +            raise RuntimeError(
      +                f"Browser Use API connection failed: {exc}"
      +            ) from exc
       
               if not response.ok:
                   if managed_mode and not _should_preserve_pending_create_key(response):
    • tools/browser_providers/browserbase.py
      @@ -92,45 +92,50 @@ def create_session(self, task_id: str) -> Dict[str, object]:
                   "X-BB-API-Key": [redacted:secret-assignment]"api_key"],
               }
       
      -        response = requests.post(
      -            f"{config['base_url']}/v1/sessions",
      -            headers=headers,
      -            json=session_config,
      -            timeout=30,
      -        )
      -
      -        proxies_fallback = False
      -        keepalive_fallback = False
      -
      -        # Handle 402 — paid features unavailable
      -        if response.status_code == 402:
      -            if enable_keep_alive:
      -                keepalive_fallback = True
      -                logger.warning(
      -                    "keepAlive may require paid plan (402), retrying without it. "
      -                    "Sessions may timeout during long operations."
      -                )
      -                session_config.pop("keepAlive", None)
      -                response = requests.post(
      -                    f"{config['base_url']}/v1/sessions",
      -                    headers=headers,
      -                    json=session_config,
      -                    timeout=30,
      -                )
      +        try:
      +            response = requests.post(
      +                f"{config['base_url']}/v1/sessions",
      +                headers=headers,
      +                json=session_config,
      +                timeout=30,
      +            )
       
      -            if response.status_code == 402 and enable_proxies:
      -                proxies_fallback = True
      -                logger.warning(
      -                    "Proxies unavailable (402), retrying without proxies. "
      -                    "Bot detection may be less effective."
      -                )
      -                session_config.pop("proxies", None)
      -                response = requests.post(
      -                    f"{config['base_url']}/v1/sessions",
      -                    headers=headers,
      -                    json=session_config,
      -                    timeout=30,
      -                )
      +            proxies_fallback = False
      +            keepalive_fallback = False
      +
      +            # Handle 402 — paid features unavailable
      +            if response.status_code == 402:
      +                if enable_keep_alive:
      +                    keepalive_fallback = True
      +                    logger.warning(
      +                        "keepAlive may require paid plan (402), retrying without it. "
      +                        "Sessions may timeout during long operations."
      +                    )
      +                    session_config.pop("keepAlive", None)
      +                    response = requests.post(
      +                        f"{config['base_url']}/v1/sessions",
      +                        headers=headers,
      +                        json=session_config,
      +                        timeout=30,
      +                    )
      +
      +                if response.status_code == 402 and enable_proxies:
      +                    proxies_fallback = True
      +                    logger.warning(
      +                        "Proxies unavailable (402), retrying without proxies. "
      +                        "Bot detection may be less effective."
      +                    )
      +                    session_config.pop("proxies", None)
      +                    response = requests.post(
      +                        f"{config['base_url']}/v1/sessions",
      +                        headers=headers,
      +                        json=session_config,
      +                        timeout=30,
      +                    )
      +        except requests.RequestException as exc:
      +            raise RuntimeError(
      +                f"Browserbase API connection failed: {exc}"
      +            ) from exc
       
               if not response.ok:
                   raise RuntimeError(
    • tools/browser_providers/firecrawl.py
      @@ -47,12 +47,17 @@ def create_session(self, task_id: str) -> Dict[str, object]:
       
               body: Dict[str, object] = {"ttl": ttl}
       
      -        response = requests.post(
      -            f"{self._api_url()}/v2/browser",
      -            headers=self._headers(),
      -            json=body,
      -            timeout=30,
      -        )
      +        try:
      +            response = requests.post(
      +                f"{self._api_url()}/v2/browser",
      +                headers=self._headers(),
      +                json=body,
      +                timeout=30,
      +            )
      +        except requests.RequestException as exc:
      +            raise RuntimeError(
      +                f"Firecrawl API connection failed: {exc}"
      +            ) from exc
       
               if not response.ok:
                   raise RuntimeError(

1 PR closed without merging

From the close comments: other 1

  • #2753 fix(tools): wrap browser provider network calls with error handling · other → #26247
Closed issues · 1
  • Closed#2746[Bug]: Unprotected network calls in browser providers crash on connection failure
How this cluster was grouped
  • Link evidence (structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
  • Pairwise link density 0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
agent
Merged PRs
#26247
Closed issues
1
Attempts
1 PR closed without merging
Fix link checked
15 May 2026

For your agent

The same facts, typed.