SeleniumHQ/selenium · error · WebDriverException

command_executor must be a RemoteConnection instance for CDP

Error message

command_executor must be a RemoteConnection instance for CDP support

What it means

Raised by start_devtools() when self.command_executor is not an instance of RemoteConnection. The CDP path needs the executor's client_config (websocket_timeout, websocket_interval) to construct the WebSocketConnection, which only exists on RemoteConnection. A custom or mocked executor that lacks client_config cannot supply these.

Source

Thrown at py/selenium/webdriver/remote/webdriver.py:1168

            if cdp_version is None:
                raise WebDriverException("CDP version not found in capabilities")
            version = cdp_version.split(".")[0]
        else:
            version, ws_url = self._get_cdp_details()

        if not ws_url:
            raise WebDriverException("Unable to find url to connect to from capabilities")

        if cdp is None:
            raise WebDriverException("CDP module not loaded")

        self._devtools = cdp.import_devtools(version)
        if self._websocket_connection:
            return self._devtools, self._websocket_connection
        if self.caps["browserName"].lower() == "firefox":
            raise RuntimeError("CDP support for Firefox has been removed. Please switch to WebDriver BiDi.")
        if not isinstance(self.command_executor, RemoteConnection):
            raise WebDriverException("command_executor must be a RemoteConnection instance for CDP support")
        self._websocket_connection = WebSocketConnection(
            ws_url,
            self.command_executor.client_config.websocket_timeout,
            self.command_executor.client_config.websocket_interval,
        )
        targets = self._websocket_connection.execute(self._devtools.target.get_targets())
        for target in targets:
            if target.target_id == self.current_window_handle:
                target_id = target.target_id
                break
        session = self._websocket_connection.execute(self._devtools.target.attach_to_target(target_id, True))
        self._websocket_connection.session_id = session
        return self._devtools, self._websocket_connection

    @asynccontextmanager
    async def bidi_connection(self):
        if self.caps["browserName"].lower() == "firefox":
            raise RuntimeError("CDP support for Firefox has been removed. Please switch to WebDriver BiDi.")

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Use selenium.webdriver.remote.remote_connection.RemoteConnection (or a subclass) as the command_executor.
  2. If you must use a custom executor, subclass RemoteConnection so isinstance passes and expose client_config.
  3. For CDP features specifically, prefer a real RemoteConnection rather than a mock.

Example fix

# before
driver = webdriver.Remote(command_executor=MyCustomExecutor(...))
driver.start_devtools()

# after
from selenium.webdriver.remote.remote_connection import RemoteConnection
driver = webdriver.Remote(command_executor=RemoteConnection(remote_url))
driver.start_devtools()
Defensive patterns

Strategy: type-guard

Validate before calling

from selenium.webdriver.remote.remote_connection import RemoteConnection
if not isinstance(driver.command_executor, RemoteConnection):
    raise TypeError('CDP requires a RemoteConnection executor')
driver.start_devtools()

Type guard

from selenium.webdriver.remote.remote_connection import RemoteConnection
def has_remote_connection(driver) -> bool:
    return isinstance(driver.command_executor, RemoteConnection)

Try / catch

from selenium.common.exceptions import WebDriverException
try:
    driver.start_devtools()
except WebDriverException as e:
    if 'RemoteConnection' in str(e):
        # recreate driver with a RemoteConnection executor
        raise

Prevention

When it happens

Trigger: Constructing a driver with a custom command_executor object (not RemoteConnection) and then calling start_devtools(). Common when subclassing WebDriver to inject a test executor or a custom HTTP transport.

Common situations: Unit tests that inject a fake executor, or custom WebDriver subclasses used for recording/replaying traffic. Also when someone passes a bare HttpConnection or a third-party executor.

Related errors


AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14). Data as JSON: /api/errors/bc3881e2e7f1c889. Report an issue: GitHub.