SeleniumHQ/selenium · error · Error::WebDriverError

These options are not w3c compliant: #{options}

Error message

These options are not w3c compliant: #{options}

What it means

Options#as_json serializes capabilities for the W3C session. It first extracts known W3C options and registered vendor capabilities; any keys left over are treated as non-compliant and raise WebDriverError. Vendor-specific or experimental capabilities must be registered through add_option rather than passed as unrecognized constructor keys.

Source

Thrown at rb/lib/selenium/webdriver/common/options.rb:136

      alias eql? ==

      #
      # @api private
      #

      def as_json(*)
        options = @options.dup

        downloads = options.delete(:enable_downloads)
        options['se:downloadsEnabled'] = downloads unless downloads.nil?
        w3c_options = process_w3c_options(options)

        browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
          capability_value = options.delete(capability_alias)
          hash[capability_name] = capability_value unless capability_value.nil?
        end

        raise Error::WebDriverError, "These options are not w3c compliant: #{options}" unless options.empty?

        browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)

        process_browser_options(browser_options)
        generate_as_json(merge_browser_options(w3c_options, browser_options))
      end

      private

      # Preserve a hand-built vendor options hash (e.g. passed through #add_option) by merging it
      # with the binding's own, rather than letting one silently overwrite the other.
      def merge_browser_options(w3c_options, browser_options)
        w3c_options.merge(browser_options) do |_key, w3c_value, browser_value|
          if w3c_value.is_a?(Hash) && browser_value.is_a?(Hash)
            browser_value.merge(w3c_value)
          else
            browser_value
          end

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Register vendor/experimental options via options.add_option(:detach, true) so they are preserved through serialization.
  2. Use the documented accessor methods (e.g. options.page_load_strategy=) for known capabilities.
  3. Inspect Options::W3C_OPTIONS and the class CAPABILITIES constant to confirm which keys are accepted in the constructor.
  4. Remove any unrecognized keys from the constructor hash and re-add them with add_option.

Example fix

# before
options = Selenium::WebDriver::Chrome::Options.new(detach: true)

# after
options = Selenium::WebDriver::Chrome::Options.new
options.add_option(:detach, true)
Defensive patterns

Strategy: validation

Validate before calling

known = (Selenium::WebDriver::Options::W3C_OPTIONS + options.class::CAPABILITIES.keys)
unknown = opts.keys - known
raise ArgumentError, "unknown options: #{unknown.inspect}" unless unknown.empty?

Type guard

def w3c_or_known?(options, key)
  Selenium::WebDriver::Options::W3C_OPTIONS.include?(key) ||
    options.class::CAPABILITIES.key?(key) || key.to_s.include?(':')
end

Try / catch

begin
  options.as_json
rescue Selenium::WebDriver::Error::WebDriverError => e
  raise unless e.message.include?('not w3c compliant')
  # move unknown keys into add_option and retry
end

Prevention

When it happens

Trigger: Constructing Options.new(some_unknown_key: value) where the key is neither a W3C option nor a registered capability. Mutating options.options directly with an arbitrary key. Typo-ing a capability name so it is not consumed by the CAPABILITIES map.

Common situations: Trying to set a browser-specific flag (e.g. a Chrome experimental option) via the constructor hash instead of add_option. Copying a capability name with a typo or wrong casing. Passing a Hash of capabilities that includes unsupported entries.

Related errors


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