NanmiCoder/MediaCrawler · error · RuntimeError
Cannot connect to existing browser on port {self.debug_port}
Error message
Cannot connect to existing browser on port {self.debug_port} after waiting {timeout}s. Please ensure:
1. Your browser is running
2. Remote debugging is enabled (chrome://inspect/#remote-debugging)
3. The debug port is {self.debug_port} (configure via CDP_DEBUG_PORT) What it means
Raised by CDPBrowserManager when connecting to an existing (already running) browser: it polls _test_cdp_connection(debug_port) once per second for `timeout` seconds and, never succeeding, reports it could not reach Chrome's DevTools endpoint. The message walks through the three prerequisites: browser running, --remote-debugging-port enabled, and the port matching CDP_DEBUG_PORT.
Source
Thrown at tools/cdp_browser.py:179
# The user may need time to enable remote debugging or confirm the connection dialog
timeout = config.BROWSER_LAUNCH_TIMEOUT
utils.logger.info(
f"[CDPBrowserManager] Waiting up to {timeout}s for browser CDP connection..."
)
connected = False
for i in range(timeout):
if await self._test_cdp_connection(self.debug_port):
connected = True
break
if i % 5 == 0 and i > 0:
utils.logger.info(
f"[CDPBrowserManager] Still waiting for browser... ({i}s elapsed) "
"Please enable remote debugging: chrome://inspect/#remote-debugging"
)
await asyncio.sleep(1)
if not connected:
raise RuntimeError(
f"Cannot connect to existing browser on port {self.debug_port} "
f"after waiting {timeout}s. Please ensure:\n"
" 1. Your browser is running\n"
" 2. Remote debugging is enabled (chrome://inspect/#remote-debugging)\n"
f" 3. The debug port is {self.debug_port} (configure via CDP_DEBUG_PORT)"
)
# Connect via CDP (reuse existing method)
await self._connect_via_cdp(playwright)
# Create browser context (reuse existing method, will prefer existing context)
browser_context = await self._create_browser_context(playwright_proxy, user_agent)
self.browser_context = browser_context
utils.logger.info("[CDPBrowserManager] Successfully connected to existing browser")
return browser_context
async def _get_browser_path(self) -> str:View on GitHub (pinned to d6f7c5bb90)
Solutions
- Relaunch your browser with the flag: chrome --remote-debugging-port=9222 (match CDP_DEBUG_PORT) and a separate --user-data-dir if needed
- Verify the endpoint answers: curl http://127.0.0.1:9222/json/version — if it fails, the browser is not exposing CDP
- Align the port: set CDP_DEBUG_PORT to the port your browser actually uses, or vice versa
- Kill other Chrome instances holding 9222 with a stale/non-debug profile
- If you don't need an existing browser, use the managed-launch path (which starts its own browser) instead
Example fix
# before chrome # normal launch, CDP not exposed -> timeout after Ns # after google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/cdp-profile & curl -s http://127.0.0.1:9222/json/version # sanity check before starting the crawler
Defensive patterns
Strategy: validation
Validate before calling
import aiohttp
async def cdp_alive(port: int) -> bool:
try:
async with aiohttp.ClientSession() as s:
async with s.get(f"http://127.0.0.1:{port}/json/version", timeout=aiohttp.ClientTimeout(total=2)) as r:
return r.status == 200
except Exception:
return False
# before starting the crawler in 'existing browser' mode:
if not await cdp_alive(config.CDP_DEBUG_PORT):
raise SystemExit(f"start chrome with --remote-debugging-port={config.CDP_DEBUG_PORT} first") Try / catch
try:
ctx = await mgr.init(color, headless=False)
except RuntimeError as e:
if "Cannot connect to existing browser" in str(e):
# actionable recovery: launch the browser ourselves with the flag
subprocess.Popen([browser, f"--remote-debugging-port={mgr.debug_port}", "--user-data-dir=/tmp/cdp"])
ctx = await mgr.init(color, headless=False) # retry after launch
else:
raise Prevention
- Pre-flight check http://127.0.0.1:<port>/json/version before connecting
- Launch Chrome with --remote-debugging-port and a dedicated --user-data-dir
- Keep CDP_DEBUG_PORT consistent between browser launch and crawler config
When it happens
Trigger: HEADLESS/OFF mode expecting a user-launched browser: Chrome was started normally (no --remote-debugging-port flag), or it listens on a different port than config.CDP_DEBUG_PORT, or the browser exits/crashes during the wait window. The CDP HTTP endpoint http://localhost:<port>/json/version never answers.
Common situations: First-time setup where the user forgets to relaunch Chrome with the debugging flag; CDP_DEBUG_PORT default (9222) clashing with another Chrome instance; SELinux/firewall blocking loopback DevTools; Chrome 111+ refusing remote debugging on the default profile without a dedicated --user-data-dir.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Crawler is already running
- Browser failed to start within {config.BROWSER_LAUNCH_TIMEOU
- No crawler is running
- File not found
- Not a file
AI-assisted analysis of NanmiCoder/MediaCrawler@d6f7c5bb90 (2026-08-15).
Data as JSON: /api/errors/10d9f304bcdde06a.
Report an issue: GitHub.