SeleniumHQ/selenium · error · ArgumentError

:options must be an instance of #{default_options.class}

Error message

:options must be an instance of #{default_options.class}

What it means

When starting a local driver, process_options validates that the supplied :options object is an instance of the Options subclass that matches the target browser (e.g. Chrome::Options for Chrome, Firefox::Options for Firefox). If the options object's class does not match, ArgumentError is raised. This prevents silently sending the wrong capability payload to the driver service.

Source

Thrown at rb/lib/selenium/webdriver/common/local_driver.rb:49

        begin
          yield(caps, http_client) if block_given?
        rescue Selenium::WebDriver::Error::WebDriverError
          @service_manager&.stop
          raise
        end
      end

      def service_url(service)
        @service_manager = service.launch
        @service_manager.uri
      end

      def process_options(options, service)
        default_options = Options.send(browser)
        options ||= default_options

        unless options.is_a?(default_options.class)
          raise ArgumentError, ":options must be an instance of #{default_options.class}"
        end

        finder = WebDriver::DriverFinder.new(options, service)
        options.binary = finder.browser_path if options.respond_to?(:binary) && finder.browser_path?
        service.executable_path = finder.driver_path
        options.browser_version = nil if options.respond_to?(:binary) && options.binary
        options.as_json
      end

      private

      def assert_local_arguments(url, http_client, client_config)
        if url || client_config&.server_url
          raise ArgumentError, "Can't set the server URL for #{self.class}; the service provides it"
        elsif http_client && client_config
          raise ArgumentError, 'Cannot use both :http_client and :client_config'
        end
      end

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Construct the Options class that matches the browser: Selenium::WebDriver::Chrome::Options.new for :chrome.
  2. If you do not need custom options, omit the :options argument so Selenium uses the default Options.send(browser) instance.
  3. Double-check that the symbol passed to Driver.for matches the Options subclass you instantiated.

Example fix

# before
options = Selenium::WebDriver::Firefox::Options.new
driver = Selenium::WebDriver.for(:chrome, options: options)

# after
options = Selenium::WebDriver::Chrome::Options.new
driver = Selenium::WebDriver.for(:chrome, options: options)
Defensive patterns

Strategy: type-guard

Validate before calling

expected = Selenium::WebDriver::Options.send(browser).class
raise ArgumentError, "options must be #{expected}" unless options.is_a?(expected)

Type guard

def options_match_browser?(options, browser)
  options.is_a?(Selenium::WebDriver::Options.send(browser).class)
end

Try / catch

begin
  Selenium::WebDriver.for(browser, options: options)
rescue ArgumentError => e
  raise unless e.message.include?('must be an instance of')
  options = Selenium::WebDriver::Options.send(browser)
  Selenium::WebDriver.for(browser, options: options)
end

Prevention

When it happens

Trigger: Passing Selenium::WebDriver::Firefox::Options.new as :options to Selenium::WebDriver.for(:chrome, options:). Passing a plain Hash or a remote Capabilities object instead of an Options instance. Mixing Edge::Options with a Chrome driver.

Common situations: Copy-pasting an Options setup block from another browser and changing only the :browser symbol. Switching the browser without updating the Options class. Passing an Options object whose class is a parent or unrelated type.

Related errors


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