SeleniumHQ/selenium · error · TypeError

expected String or Symbol, got #{key.inspect}:#{key.class}

Error message

expected String or Symbol, got #{key.inspect}:#{key.class}

What it means

convert_json_key normalizes hash keys during JSON serialization and accepts only String or Symbol keys. After converting a Symbol to a String (and optionally camelCasing it), any remaining non-String key raises TypeError. This typically originates from an Integer or arbitrary object used as an options key via add_option or direct hash mutation.

Source

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

        end
      end

      def process_json_hash(value, camelize_keys)
        value.each_with_object({}) do |(key, val), hash|
          next if val.respond_to?(:empty?) && val.empty?

          camelize = camelize_keys ? camelize?(key) : false
          key = convert_json_key(key, camelize: camelize)
          hash[key] = generate_as_json(val, camelize_keys: camelize)
        end
      end

      def convert_json_key(key, camelize: true)
        key = key.to_s if key.is_a?(Symbol)
        key = camel_case(key) if camelize
        return key if key.is_a?(String)

        raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
      end

      def camel_case(str)
        str.gsub(/_([a-z])/) { Regexp.last_match(1)&.upcase }
      end
    end # Options
  end # WebDriver
end # Selenium

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Use only String or Symbol keys when calling add_option or mutating options.options.
  2. Convert numeric/object keys to Symbols or Strings before adding them.
  3. Validate that every key in a dynamically-built options hash is_a?(String) || is_a?(Symbol).

Example fix

# before
options.add_option(123, true)

# after
options.add_option(:'option_123', true)
Defensive patterns

Strategy: type-guard

Validate before calling

raise TypeError, 'option key must be String or Symbol' unless key.is_a?(String) || key.is_a?(Symbol)

Type guard

def valid_option_key?(key)
  key.is_a?(String) || key.is_a?(Symbol)
end

Try / catch

begin
  options.add_option(key, value)
rescue TypeError => e
  raise unless e.message.include?('expected String or Symbol')
  options.add_option(key.to_s, value)
end

Prevention

When it happens

Trigger: Calling options.add_option(123, value) with an Integer key. Storing an object (non-String/Symbol) as a key in the options hash. Using a Class or Numeric as an option key.

Common situations: Programmatically generating option keys from numeric IDs. Accidentally storing a configuration object as a hash key. Migrating data structures that use Integer keys.

Related errors


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