xtekky/gpt4free · error · TimeoutError
CDP call {method} timed out after 30 seconds
Error message
CDP call {method} timed out after 30 seconds What it means
Raised by CDPSession.call() in g4f/requests/cdp.py when the CDP command was sent over the WebSocket but no matching response (by request id) arrived within a hard-coded 30 second asyncio.wait_for. The pending future is cleaned up in finally, and the TimeoutError surfaces with the method name. Typical causes are a hung renderer, a dead-but-not-closed socket, or a genuinely slow command like a navigation that never finishes.
Source
Thrown at g4f/requests/cdp.py:447
async def call(self, method: str, **params) -> dict:
"""Call a CDP method and wait for its result."""
if not self.ws:
raise RuntimeError("CDPSession is not connected")
self.id_counter += 1
req_id = self.id_counter
fut = asyncio.get_running_loop().create_future()
self._pending_requests[req_id] = fut
payload = {"id": req_id, "method": method, "params": params}
await self.ws.send_json(payload)
try:
return await asyncio.wait_for(fut, timeout=30.0)
except asyncio.TimeoutError:
raise TimeoutError(f"CDP call {method} timed out after 30 seconds")
finally:
self._pending_requests.pop(req_id, None)
async def wait_for_event(self, method: str, timeout: float = 30.0) -> dict:
"""Wait for a specific CDP event to fire (one-time)."""
fut = asyncio.get_running_loop().create_future()
if method not in self._event_handlers:
self._event_handlers[method] = []
self._event_handlers[method].append(fut)
try:
return await asyncio.wait_for(fut, timeout=timeout)
except asyncio.TimeoutError:
self._event_handlers[method].remove(fut)
raise TimeoutError(f"Timeout waiting for event {method}")
def add_event_handler(self, method: str, queue: asyncio.Queue):
"""Add a persistent event listener that pushes events to an asyncio.Queue."""View on GitHub (pinned to 973504e177)
Solutions
- Retry the call once — transient browser hiccups often clear.
- If it reproduces on a specific navigate/evaluate, test that page manually in the same Chrome to find what hangs (infinite loop, blocking dialog, unreachable subresource).
- Restart the shared browser process (kill chrome / let g4f's lock logic recycle it) to recover a frozen instance.
- Give the container more CPU/memory; a starved Chrome routinely misses 30s deadlines.
- Split very long operations: navigate with a shorter expectation, then poll via evaluate_js instead of one 30s+ call.
Example fix
// before
result = await session.call("Page.navigate", url=slow_page) # may exceed 30s
// after
for attempt in range(3):
try:
result = await session.call("Page.navigate", url=slow_page)
break
except TimeoutError:
if attempt == 2:
raise Defensive patterns
Strategy: retry
Try / catch
try:
result = await session.call("Page.navigate", url=url)
except TimeoutError as e:
log.warning(f"{e}; restarting browser and retrying once")
await restart_browser()
result = await session.call("Page.navigate", url=url) Prevention
- Keep individual CDP operations short; poll state instead of one long call.
- Monitor chrome process health (memory/CPU) in long-running services and recycle proactively.
- Budget container resources so Chrome is not starved past the hard-coded 30s.
When it happens
Trigger: Calling Page.navigate to a page that never fires load; Runtime.evaluate on a script with an infinite loop; the browser process froze (OOM, GPU hang); the WebSocket dropped silently so responses never arrive.
Common situations: Heavy pages under memory pressure; sandboxed containers with limited CPU so Chrome is starved; long-running Turnstile/Cloudflare challenges exceeding 30s; network flakiness between client and a remote-hosted Chrome.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Missing CDP requirements
- Failed to start shared Chrome on port {port}
- Failed to create new tab target on port {self.port}
- Timeout waiting for event {method}
- WebSocket Error: {ws.exception()}
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/81928001fb266d3d.
Report an issue: GitHub.