Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions src/browser_harness/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def get_ws_url():
except (OSError, KeyError, ValueError):
time.sleep(1)
raise RuntimeError(
f"Chrome's remote-debugging page is open, but DevTools is not live yet on 127.0.0.1:{port} — if Chrome opened a profile picker, choose your normal profile first, then tick the checkbox and click Allow if shown"
f"Chrome's remote-debugging page is open, but DevTools is not live yet on 127.0.0.1:{port} (profile: {base}) — if Chrome opened a profile picker, choose your normal profile first, then tick the checkbox and click Allow if shown"
)
for probe_port in (9222, 9223):
try:
Expand Down Expand Up @@ -185,16 +185,33 @@ async def start(self):
url = get_ws_url()
log(f"connecting to {url}")
self.cdp = CDPClient(url)
try:
await self.cdp.start()
except Exception as e:
_ATTEMPTS = 3
_RETRY_DELAY = 5 # seconds between WS handshake retries
last_exc = None
for attempt in range(_ATTEMPTS):
if attempt > 0:
await asyncio.sleep(_RETRY_DELAY)
try:
url = get_ws_url()
except Exception:
pass # reuse previous URL if refresh fails
log(f"retry {attempt}: connecting to {url}")
self.cdp = CDPClient(url)
try:
await self.cdp.start()
break
except Exception as e:
last_exc = e
if attempt < _ATTEMPTS - 1:
log(f"handshake attempt {attempt + 1} failed ({e}); retrying in {_RETRY_DELAY}s")
else:
if os.environ.get("BU_CDP_WS"):
raise RuntimeError(
f"CDP WS handshake failed: {e} -- remote browser WebSocket connection failed. "
f"CDP WS handshake failed: {last_exc} -- remote browser WebSocket connection failed. "
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot May 22, 2026

Choose a reason for hiding this comment

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

P2: Remote handshake error branch omits the WS URL, leaving the error-context guarantee only partially implemented. The local branch includes ({url}) but the remote branch does not, despite the PR stating WS URL should be included on all raise paths.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/browser_harness/daemon.py, line 210:

<comment>Remote handshake error branch omits the WS URL, leaving the error-context guarantee only partially implemented. The local branch includes `({url})` but the remote branch does not, despite the PR stating WS URL should be included on all raise paths.</comment>

<file context>
@@ -185,16 +185,33 @@ async def start(self):
             if os.environ.get("BU_CDP_WS"):
                 raise RuntimeError(
-                    f"CDP WS handshake failed: {e} -- remote browser WebSocket connection failed. "
+                    f"CDP WS handshake failed: {last_exc} -- remote browser WebSocket connection failed. "
                     "This can happen when network policy blocks the connection, the WS URL is wrong or expired, or the remote endpoint is down. "
                     "If you use Browser Use cloud, verify BROWSER_USE_API_KEY and get a fresh URL via start_remote_daemon()."
</file context>
Suggested change
f"CDP WS handshake failed: {last_exc} -- remote browser WebSocket connection failed. "
f"CDP WS handshake failed ({url}): {last_exc} -- remote browser WebSocket connection failed. "
Fix with Cubic

"This can happen when network policy blocks the connection, the WS URL is wrong or expired, or the remote endpoint is down. "
"If you use Browser Use cloud, verify BROWSER_USE_API_KEY and get a fresh URL via start_remote_daemon()."
)
raise RuntimeError(f"CDP WS handshake failed: {e} -- click Allow in Chrome if prompted, then retry")
raise RuntimeError(f"CDP WS handshake failed ({url}): {last_exc} -- click Allow in Chrome if prompted, then retry")
await self.attach_first_page()
orig = self.cdp._event_registry.handle_event
mark_js = "if(!document.title.startsWith('\U0001F7E2'))document.title='\U0001F7E2 '+document.title"
Expand Down