{"record":{"id":"9f61c85d8bb9b1c5","repo":"SeleniumHQ/selenium","slug":"don-t-use-both-options-and-capabilities-when-ini","errorCode":null,"errorMessage":"Don't use both :options and :capabilities when initializing #{self.class}, prefer :options","messagePattern":"Don't use both :options and :capabilities when initializing #(.+?), prefer :options","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"rb/lib/selenium/webdriver/remote/driver.rb","lineNumber":72,"sourceCode":"          raise ArgumentError, 'Cannot use both :http_client and :client_config' if http_client && client_config\n          raise ArgumentError, 'Cannot use both :url and a ClientConfig#server_url' if url && client_config&.server_url\n        end\n\n        def devtools_url\n          capabilities['se:cdp']\n        end\n\n        def devtools_version\n          cdp_version = capabilities['se:cdpVersion']&.split('.')&.first\n          raise Error::WebDriverError, 'DevTools is not supported by the Remote Server' unless cdp_version\n\n          Integer(cdp_version)\n        end\n\n        def process_options(options, capabilities)\n          if options && capabilities\n            msg = \"Don't use both :options and :capabilities when initializing #{self.class}, prefer :options\"\n            raise ArgumentError, msg\n          elsif options.nil? && capabilities.nil?\n            raise ArgumentError, \"#{self.class} needs :options to be set\"\n          end\n          options ? options.as_json : generate_capabilities(capabilities)\n        end\n\n        def generate_capabilities(capabilities)\n          Array(capabilities).map { |cap|\n            if cap.is_a? Symbol\n              cap = WebDriver::Options.send(cap)\n            elsif !cap.respond_to? :as_json\n              msg = \":capabilities parameter only accepts objects responding to #as_json which #{cap.class} does not\"\n              raise ArgumentError, msg\n            end\n            cap.as_json\n          }.inject(:merge)\n        end\n      end # Driver","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/rb/lib/selenium/webdriver/remote/driver.rb#L54-L90","documentation":"Raised by Remote::Driver#process_options when both :options and :capabilities keyword arguments are provided to the driver constructor. The library wants a single source of truth for session configuration; :options (an Options object) is the modern preferred API while :capabilities (legacy) is supported separately. Passing both is ambiguous and rejected to prevent one silently overriding the other.","triggerScenarios":"Calling Selenium::WebDriver.for(:remote, url: url, options: opts, capabilities: caps). Migrating from capabilities to options but leaving the old capabilities argument in place. Passing a shared config hash that happens to contain both keys.","commonSituations":"Gradual migration from the deprecated :capabilities API to :options. Copy-pasting from mixed documentation examples. Config builders that set both 'just in case'. Using Selenium 3-era code with a Selenium 4+ gem.","solutions":["Remove :capabilities and use only :options: Selenium::WebDriver.for(:remote, url: url, options: Selenium::WebDriver::Options.chrome).","If you must use legacy capabilities temporarily, remove :options and pass only :capabilities.","Consolidate all capability settings into a single Options object instead of splitting across both parameters."],"exampleFix":"# before\ndriver = Selenium::WebDriver.for(:remote, url: url,\n  options: Selenium::WebDriver::Options.chrome,\n  capabilities: Selenium::WebDriver::Remote::Capabilities.chrome)\n\n# after\ndriver = Selenium::WebDriver.for(:remote, url: url,\n  options: Selenium::WebDriver::Options.chrome)","handlingStrategy":"validation","validationCode":"# Ensure only one of :options or :capabilities:\nif config[:options] && config[:capabilities]\n  config.delete(:capabilities)  # prefer :options\nend\nSelenium::WebDriver.for(:remote, **config)","typeGuard":"def single_session_config?(config)\n  !(config[:options] && config[:capabilities])\nend","tryCatchPattern":"begin\n  Selenium::WebDriver.for(:remote, **config)\nrescue ArgumentError => e\n  config.delete(:capabilities) if e.message.include?('options and :capabilities')\n  Selenium::WebDriver.for(:remote, **config)\nend","preventionTips":["Standardize on :options for all new Selenium 4+ code.","Remove all :capabilities usage during migration to :options.","Audit config builders for both keys before driver creation."],"tags":["argument-error","remote-driver","options","capabilities","migration"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}