browser-use/browser-use · error · TimeoutError
CDP method {method!r} did not respond within {self._cdp_requ
Error message
CDP method {method!r} did not respond within {self._cdp_request_timeout_s:.0f}s. The browser may be unresponsive (silent WebSocket — container crashed or proxy lost upstream). What it means
A CDPConnection wrapper enforces a per-request timeout (`_cdp_request_timeout_s`) around every raw CDP WebSocket send. When a method (e.g. Page.navigate, Runtime.evaluate) gets no response frame within the window, it raises TimeoutError with the method name and a hint: the WebSocket stayed open but silent, typical of a crashed browser container or a proxy that lost its upstream connection. It deliberately raises plain TimeoutError so existing handlers match uniformly.
Source
Thrown at browser_use/browser/_cdp_timeout.py:122
) -> None:
super().__init__(*args, **kwargs)
self._cdp_request_timeout_s: float = _coerce_valid_timeout(cdp_request_timeout_s)
async def send_raw(
self,
method: str,
params: Any | None = None,
session_id: str | None = None,
) -> dict[str, Any]:
try:
return await asyncio.wait_for(
super().send_raw(method=method, params=params, session_id=session_id),
timeout=self._cdp_request_timeout_s,
)
except TimeoutError as e:
# Raise a plain TimeoutError so existing `except TimeoutError`
# handlers in browser-use / tools treat this uniformly.
raise TimeoutError(
f'CDP method {method!r} did not respond within {self._cdp_request_timeout_s:.0f}s. '
f'The browser may be unresponsive (silent WebSocket — container crashed or proxy lost upstream).'
) from e
View on GitHub (pinned to 6c73fced2f)
Solutions
- Treat it as a dead browser: tear down the session (`await browser.close()`) and recreate it, then retry the task — a hung CDP socket rarely recovers.
- If genuinely slow operations are expected, raise `_cdp_request_timeout_s` on the CDP connection config.
- For containers: add memory/CPU headroom or a Chrome watchdog to stop silent OOM kills.
- For `cdp_url` setups: verify the proxy/upstream health independently before blaming the page.
Example fix
# before
state = await agent.run() # mid-run CDP hang surfaces as TimeoutError, run keeps waiting
# after
import asyncio
from browser_use import Agent, Browser
async def main():
try:
return await Agent(task=t, llm=llm, browser=Browser()).run(max_steps=20)
except TimeoutError:
await browser.close() # kill dead session
return await Agent(task=t, llm=llm, browser=Browser()).run(max_steps=20) # fresh retry Defensive patterns
Strategy: retry
Validate before calling
# Pre-flight: cheap CDP round-trip before launching a long task
async def cdp_alive(browser, timeout_s=10) -> bool:
try:
conn = await browser._get_cdp_connection() if hasattr(browser, '_get_cdp_connection') else None
if conn is None:
return True # cannot probe; assume ok
await asyncio.wait_for(conn.send_raw('Browser.getVersion'), timeout=timeout_s)
return True
except TimeoutError:
return False Try / catch
async def run_resilient(task, llm, max_restarts=2):
for attempt in range(max_restarts + 1):
browser = Browser()
try:
agent = Agent(task=task, llm=llm, browser=browser)
return await agent.run()
except TimeoutError as e:
if 'CDP method' not in str(e) or attempt == max_restarts:
raise
logger.warning('CDP hang (%s); recreating browser', e)
finally:
await browser.close() Prevention
- Give containerized Chrome memory/CPU headroom and a supervisor that restarts it on OOM.
- For `cdp_url` connections, monitor upstream health; a silent WebSocket means the far end died.
- Wrap long tasks in a browser-recreate loop keyed on TimeoutError with 'CDP method' in the message.
When it happens
Trigger: Any CDP operation while the browser process is hung or dead-but-socket-open: OOM-killed headless Chrome in Docker, a remote browser behind a proxy whose upstream dropped, frozen page due to GPU/render deadlock, or an extremely slow method exceeding the configured timeout.
Common situations: Long-running automation in containers where Chrome gets OOM-reaped; remote/CDP-URL setups (`cdp_url=`) through flaky proxies; heavy pages (infinite loops in JS) blocking the CDP response thread; timeouts surfacing after network changes mid-session.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- connect() timed out after 15s — CDP connection to {self.cdp_
- Page.navigate() timed out after {nav_timeout}s ({duration_ms
- Failed to establish CDP connection to browser: {e}
- Failed to get dropdown options for index {index_for_logging}
- Browser did not start within {timeout} seconds
AI-assisted analysis of browser-use/browser-use@6c73fced2f (2026-08-14).
Data as JSON: /api/errors/dfbd33df757a50c6.
Report an issue: GitHub.