SeleniumHQ/selenium · error · ArgumentError
#{opts.inspect} invalid for #{command.inspect}
Error message
#{opts.inspect} invalid for #{command.inspect} What it means
Raised by Bridge#execute when the opts hash passed to a command contains a placeholder key that does not exist in that command's URL path template. The bridge iterates opts and substitutes each key.inspect (e.g. ':window_handle') into the path string via String#[]=; when the placeholder is absent Ruby raises IndexError, which is rescued and re-raised as this ArgumentError. It signals a mismatch between the command's registered path and the parameters the caller supplied.
Source
Thrown at rb/lib/selenium/webdriver/remote/bridge.rb:627
private
#
# executes a command on the remote server.
#
# @return [WebDriver::Remote::Response]
#
def execute(command, opts = {}, command_hash = nil)
verb, path = commands(command) || raise(ArgumentError, "unknown command: #{command.inspect}")
path = path.dup
path[':session_id'] = session_id if path.include?(':session_id')
begin
opts.each { |key, value| path[key.inspect] = escaper.escape(value.to_s) }
rescue IndexError
raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
end
WebDriver.logger.debug("-> #{verb.to_s.upcase} #{path}", id: :command)
http.call(verb, path, command_hash)['value']
end
def escaper
@escaper ||= defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
end
def commands(command)
command_list[command] || Bridge.extra_commands[command]
end
def unwrap_script_result(arg)
case arg
when Array
arg.map { |e| unwrap_script_result(e) }View on GitHub (pinned to aa36b38e69)
Solutions
- Inspect the command's registered path template in the commands hash (or Bridge.extra_commands) and ensure every key in opts has a matching ':key' placeholder in the path.
- Remove any opts keys that have no corresponding placeholder in the path, or add the missing placeholder to the path template when registering the command.
- If using a custom command via add_commands, double-check the path string uses ':session_id' and any other ':symbol' placeholders exactly as they appear as Symbol keys in opts.
- Enable debug logging (WebDriver.logger.level = :debug, id: :command) to see the verb and path being built before the substitution fails.
Example fix
# before
bridge.execute(:my_custom_cmd, {window: 'win1', extra: 'x'})
# path is "/session/:session_id/custom" -> :window and :extra have no placeholder
# after
bridge.add_commands({my_custom_cmd: [:post, '/session/:session_id/window/:window']})
bridge.execute(:my_custom_cmd, {window: 'win1'}) Defensive patterns
Strategy: validation
Validate before calling
# Before calling execute on a custom command, validate opts keys match the path template:
path_template = bridge.commands(command_name)&.last
expected_placeholders = path_template&.scan(/:(\w+)/)&.flatten&.map(&:to_sym)
extra_keys = opts.keys - expected_placeholders
raise ArgumentError, "opts contain keys with no placeholder: #{extra_keys}" unless extra_keys.empty? Type guard
# Confirm all opts keys are Symbols that appear as ':name' in the path:
def valid_execute_opts?(command, opts, bridge)
path = bridge.commands(command)&.last
return false unless path
placeholders = path.scan(/:(\w+)/).flatten.map(&:to_sym)
opts.keys.all? { |k| k.is_a?(Symbol) && placeholders.include?(k) }
end Try / catch
begin
bridge.execute(:my_command, {key: 'val'})
rescue ArgumentError => e
WebDriver.logger.warn("Command path mismatch: #{e.message}", id: :command)
# inspect bridge.commands(:my_command) and adjust opts or re-register the command
end Prevention
- When registering custom commands, document the expected opts keys next to the path template.
- Use Symbol keys consistently for opts — the path uses key.inspect which includes the colon.
- Write a unit test that calls each custom command with its expected opts to catch mismatches early.
When it happens
Trigger: Calling bridge.execute(:some_command, {extra_key: 'val}) where :some_command's path template (from commands(command) or Bridge.extra_commands) does not contain the ':extra_key' placeholder. Also triggered when a custom command is registered via add_commands with a path missing a placeholder that the caller then passes in opts. Passing the wrong command symbol whose path expects different placeholders than the opts provided.
Common situations: Registering a custom BiDi or vendor extension command with a path template like '/session/:session_id/foo' but then calling execute with opts keys that don't match. Mistyping a placeholder key in opts (e.g. ':windowHandle' vs ':window_handle'). Using a command symbol that was never registered (though that hits the 'unknown command' raise first). Version changes that rename path placeholders without updating caller code.
Related errors
- incompatible proxy type #{type.inspect} (already set to #{@t
- cannot find element by #{how.inspect}
- cannot find elements by #{how.inspect}
- expected #{arg.inspect}:#{arg.class} to respond to #shift
- expected #{arr.inspect} to have 2 elements
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/838a244051758459.
Report an issue: GitHub.