SeleniumHQ/selenium · error · Error::WebDriverError

BiDi was enabled, but the remote end did not return a valid

Error message

BiDi was enabled, but the remote end did not return a valid webSocketUrl: #{url.inspect}.

What it means

Raised by BiDiBridge#validated_socket_url (Error::WebDriverError) during BiDi session creation when the webSocketUrl capability returned by the remote end is missing or not a ws:///wss:// URL. Selenium requested BiDi (the capabilities included the webSocketUrl flag) but the server did not hand back a usable WebSocket endpoint to connect to.

Source

Thrown at rb/lib/selenium/webdriver/remote/bidi_bridge.rb:86

        def quit
          bidi&.close
        rescue *QUIT_ERRORS
          nil
        ensure
          super
        end

        def close
          execute(:close_window).tap { |handles| bidi.close if handles.empty? }
        end

        private

        def validated_socket_url
          url = @capabilities[:web_socket_url]
          return url if url.is_a?(String) && url.start_with?('ws://', 'wss://')

          raise Error::WebDriverError,
                "BiDi was enabled, but the remote end did not return a valid webSocketUrl: #{url.inspect}."
        end

        def browsing_context
          @browsing_context ||= BiDi::Protocol::BrowsingContext.new(connection)
        end

        def readiness_state
          READINESS_STATE.fetch(capabilities[:page_load_strategy] || 'normal')
        end
      end # BiDiBridge
    end # Remote
  end # WebDriver
end # Selenium

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Upgrade the browser, driver, and Selenium Grid/Server to versions that support WebDriver BiDi.
  2. Confirm the remote end actually supports BiDi (check returned capabilities for webSocketUrl) before enabling it.
  3. If BiDi is optional, fall back to disabling webSocketUrl: true when the remote end does not support it.

Example fix

// before
options = Selenium::WebDriver::Firefox::Options.new(web_socket_url: true)
driver = Selenium::WebDriver.for(:remote, url: grid_url, capabilities: options)
# remote returns no webSocketUrl -> error

// after
# ensure grid/browser/driver support BiDi, then
options = Selenium::WebDriver::Firefox::Options.new(web_socket_url: true)
driver = Selenium::WebDriver.for(:remote, url: grid_url, capabilities: options)
Defensive patterns

Strategy: validation

Validate before calling

# Probe support before requiring BiDi
session_caps = driver.capabilities
unless session_caps[:web_socket_url].to_s.start_with?('ws')
  raise 'Remote end does not support WebDriver BiDi; disable web_socket_url or upgrade'
end

Try / catch

begin
  driver = Selenium::WebDriver.for(:remote, url: url, capabilities: bidi_options)
rescue Selenium::WebDriver::Error::WebDriverError => e
  raise unless e.message.include?('webSocketUrl')
  # fall back to classic mode without BiDi
  driver = Selenium::WebDriver.for(:remote, url: url, capabilities: classic_options)
end

Prevention

When it happens

Trigger: Enabling webSocketUrl: true in capabilities against a remote end (older driver or Grid) that does not support the WebDriver BiDi protocol; the server accepted the session but omitted/returned a malformed webSocketUrl.

Common situations: Using an outdated browser/driver or Selenium Grid version that predates BiDi support; pointing at a third-party grid that strips the webSocketUrl capability; enabling BiDi without ensuring the remote advertises it.

Related errors


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