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

  1. 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.
  2. 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.
  3. 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.
  4. 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 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


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