SeleniumHQ/selenium · error · ArgumentError

Invalid arguments: #{opts.keys}

Error message

Invalid arguments: #{opts.keys}

What it means

Raised by VirtualAuthenticatorOptions#initialize when keyword arguments contain keys other than the six recognized options: :protocol, :transport, :resident_key, :user_verification, :user_consenting, :user_verified. After deleting known keys from the opts hash, any remaining keys trigger ArgumentError listing the unexpected ones.

Source

Thrown at rb/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb:45

    class VirtualAuthenticatorOptions
      PROTOCOL = {ctap2: 'ctap2', u2f: 'ctap1/u2f'}.freeze
      TRANSPORT = {ble: 'ble', usb: 'usb', nfc: 'nfc', internal: 'internal'}.freeze

      attr_accessor :protocol, :transport, :resident_key, :user_verification, :user_consenting, :user_verified
      alias resident_key? resident_key
      alias user_verification? user_verification
      alias user_consenting? user_consenting
      alias user_verified? user_verified

      def initialize(**opts)
        @protocol = opts.delete(:protocol) { :ctap2 }
        @transport = opts.delete(:transport) { :usb }
        @resident_key = opts.delete(:resident_key) { false }
        @user_verification = opts.delete(:user_verification) { false }
        @user_consenting = opts.delete(:user_consenting) { true }
        @user_verified = opts.delete(:user_verified) { false }

        raise ArgumentError, "Invalid arguments: #{opts.keys}" unless opts.empty?
      end

      #
      # @api private
      #

      def as_json(*)
        {'protocol' => PROTOCOL[protocol],
         'transport' => TRANSPORT[transport],
         'hasResidentKey' => resident_key?,
         'hasUserVerification' => user_verification?,
         'isUserConsenting' => user_consenting?,
         'isUserVerified' => user_verified?}
      end
    end # VirtualAuthenticatorOptions
  end # WebDriver
end # Selenium

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Use only recognized snake_case keys: protocol:, transport:, resident_key:, user_verification:, user_consenting:, user_verified:.
  2. Valid values for protocol: :ctap2 (default) or :u2f. For transport: :ble, :usb (default), :nfc, :internal.
  3. Filter external data before passing: opts.slice(:protocol, :transport, :resident_key, :user_verification, :user_consenting, :user_verified).

Example fix

// before
opts = Selenium::WebDriver::VirtualAuthenticatorOptions.new(
  protoccol: :u2f,          # typo
  hasResidentKey: true,     # camelCase
  userVerification: true    # camelCase
)

// after
opts = Selenium::WebDriver::VirtualAuthenticatorOptions.new(
  protocol: :u2f,
  resident_key: true,
  user_verification: true
)
Defensive patterns

Strategy: validation

Validate before calling

VALID_VA_OPTS = %i[protocol transport resident_key user_verification user_consenting user_verified].freeze

def safe_va_options(opts)
  unknown = opts.keys - VALID_VA_OPTS
  raise ArgumentError, "Unknown VirtualAuthenticatorOptions keys: #{unknown}. Valid: #{VALID_VA_OPTS}" unless unknown.empty?
  Selenium::WebDriver::VirtualAuthenticatorOptions.new(**opts)
end

Type guard

def valid_va_opts?(opts)
  (opts.keys - %i[protocol transport resident_key user_verification user_consenting user_verified]).empty?
end

Try / catch

begin
  va_opts = Selenium::WebDriver::VirtualAuthenticatorOptions.new(**opts)
rescue ArgumentError => e
  raise unless e.message.include?('Invalid arguments')
  filtered = opts.slice(:protocol, :transport, :resident_key, :user_verification, :user_consenting, :user_verified)
  va_opts = Selenium::WebDriver::VirtualAuthenticatorOptions.new(**filtered)
end

Prevention

When it happens

Trigger: Calling VirtualAuthenticatorOptions.new(protoccol: :u2f) (typo). Passing :hasResidentKey (camelCase from the JSON spec) instead of :resident_key. Passing :userVerification instead of :user_verification. Passing an unrelated key like :name or :browser.

Common situations: Translating WebAuthn spec JSON fields (camelCase) to Ruby kwargs (snake_case) incorrectly. Typos in option names. Passing a Hash from external/config data without filtering.

Related errors


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