SeleniumHQ/selenium · error · ArgumentError
Cannot use both :http_client and :client_config
Error message
Cannot use both :http_client and :client_config
What it means
Raised by Remote::Driver#assert_arguments when both :http_client and :client_config keyword arguments are provided simultaneously. The driver can only derive its HTTP transport from one source: either a pre-built http_client object or a ClientConfig that the driver uses to build one internally — supplying both creates an ambiguous, conflicting configuration.
Source
Thrown at rb/lib/selenium/webdriver/remote/driver.rb:54
assert_arguments(service, url, http_client, client_config)
caps = process_options(options, capabilities)
http_client ||= Remote::Http::Default.new(client_config: client_config)
server_url = url || client_config&.server_url || "http://#{Platform.localhost}:4444/wd/hub"
http_client.server_url = server_url
caps['se:remoteUrl'] = server_url.to_s.chomp('/')
super(caps: caps, http_client: http_client, **)
@bridge.file_detector = ->((filename, *)) { File.exist?(filename) && filename.to_s }
command_list = @bridge.command_list
@bridge.extend(WebDriver::Remote::Features)
@bridge.add_commands(command_list)
end
private
def assert_arguments(service, url, http_client, client_config)
raise ArgumentError, "Can not set :service object on #{self.class}" if service
raise ArgumentError, 'Cannot use both :http_client and :client_config' if http_client && client_config
raise ArgumentError, 'Cannot use both :url and a ClientConfig#server_url' if url && client_config&.server_url
end
def devtools_url
capabilities['se:cdp']
end
def devtools_version
cdp_version = capabilities['se:cdpVersion']&.split('.')&.first
raise Error::WebDriverError, 'DevTools is not supported by the Remote Server' unless cdp_version
Integer(cdp_version)
end
def process_options(options, capabilities)
if options && capabilities
msg = "Don't use both :options and :capabilities when initializing #{self.class}, prefer :options"
raise ArgumentError, msgView on GitHub (pinned to aa36b38e69)
Solutions
- Choose one HTTP configuration method: pass :client_config only, or :http_client only.
- If you have a ClientConfig and need custom HTTP behavior, let the driver build the client from client_config rather than also passing http_client.
- Audit shared config hashes to ensure only one of the two keys is present before driver creation.
Example fix
# before driver = Selenium::WebDriver.for(:remote, url: url, http_client: Selenium::WebDriver::Remote::Http::Default.new, client_config: Selenium::WebDriver::Remote::ClientConfig.new(server_url: url)) # after driver = Selenium::WebDriver.for(:remote, client_config: Selenium::WebDriver::Remote::ClientConfig.new(server_url: url, read_timeout: 120))
Defensive patterns
Strategy: validation
Validate before calling
# Ensure only one HTTP config source: if config[:http_client] && config[:client_config] raise ArgumentError, 'Pass either :http_client or :client_config, not both' end
Type guard
def single_http_config?(config) !(config[:http_client] && config[:client_config]) end
Try / catch
begin
Selenium::WebDriver.for(:remote, **config)
rescue ArgumentError => e
config.delete(:http_client) if e.message.include?('http_client')
Selenium::WebDriver.for(:remote, **config)
end Prevention
- Standardize on :client_config for new code; remove legacy :http_client usage.
- Audit shared config builders for both keys before driver creation.
- Document the migration path from http_client to client_config in your codebase.
When it happens
Trigger: Calling Selenium::WebDriver.for(:remote, url: url, http_client: my_client, client_config: config). Reusing a shared config hash that includes client_config and also passing an explicit http_client. Migrating from http_client to client_config without removing the old argument.
Common situations: Gradual migration from the legacy :http_client API to the newer :client_config API where both end up in the call. Centralized config builders that set both defensively. Copying code snippets from different documentation versions.
Related errors
- Can not set :service object on #{self.class}
- Cannot use both :client_config and :open_timeout/:read_timeo
- Don't use both :options and :capabilities when initializing
- #{self.class} needs :options to be set
- too many redirects
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/2750f926002ac6a5.
Report an issue: GitHub.