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
Raised as a TypeError by Capabilities#convert_key when a capability key is neither a String nor a Symbol. convert_key normalizes keys to camelCase strings for the W3C/JSON wire protocol; String keys pass through as-is, Symbol keys are camel-cased, and any other type (Integer, Array, nil used as key) is rejected because it cannot form a valid capability name.
Source
Thrown at rb/lib/selenium/webdriver/remote/capabilities.rb:252
when Hash
value.each_with_object({}) do |(k, v), h|
h[convert_key(k)] = process_capabilities(k, v, h)
end
when Capabilities, Options
value.as_json
else
convert_value(key, value)
end
end
def convert_key(key)
case key
when String
key.to_s
when Symbol
self.class.camel_case(key)
else
raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
end
end
def convert_value(key, value)
case key
when :platform
value.to_s.upcase
when :proxy
value&.as_json
when :unhandled_prompt_behavior
value.is_a?(Symbol) ? value.to_s.tr('_', ' ') : value
else
value
end
end
end # Capabilities
end # Remote
end # WebDriverView on GitHub (pinned to aa36b38e69)
Solutions
- Ensure all capability keys are Symbols (preferred) or Strings: caps[:browserName] = 'chrome'.
- When loading from external data, coerce keys: external.each { |k, v| caps[k.to_sym] = v }.
- Filter out non-string/symbol keys before assignment if the source data is untrusted or mixed.
Example fix
# before
config.each { |k, v| caps[k] = v } # k may be Integer
# after
config.each { |k, v| caps[k.to_sym] = v if k.respond_to?(:to_sym) } Defensive patterns
Strategy: validation
Validate before calling
# Coerce keys to Symbol before assignment:
safe_keys = external_hash.select { |k, _| k.is_a?(String) || k.is_a?(Symbol) }
safe_keys.each { |k, v| capabilities[k.to_sym] = v } Type guard
def valid_capability_key?(key) key.is_a?(String) || key.is_a?(Symbol) end
Try / catch
begin capabilities[key] = value rescue TypeError capabilities[key.to_sym] = value if key.respond_to?(:to_sym) end
Prevention
- Use Symbol keys consistently for all capabilities.
- When loading from external data (YAML, JSON), coerce keys with .to_sym.
- Filter out non-string/symbol keys from untrusted sources before assignment.
When it happens
Trigger: Using an Integer as a key: caps[0] = 'value' followed by serialization. Passing a hash with non-string/symbol keys via the Capabilities constructor. Iterating over external data (e.g. parsed JSON with integer keys from a numeric-indexed structure) and assigning each to capabilities. Using a Class or Module object as a key.
Common situations: Loading capability overrides from YAML/JSON where keys are deserialized as non-strings in edge cases. Programmatic hash building that accidentally uses an integer index. Passing a Data/Struct field name object instead of a symbol. Refactoring from indifferent-access hashes that exposed integer lookups.
Related errors
- These options are not w3c compliant: #{options}
- expected String or Symbol, got #{key.inspect}:#{key.class}
- expected Hash or #{Proxy.name}, got #{proxy.inspect}:#{proxy
- :capabilities parameter only accepts objects responding to #
- no capabilities provided for merge
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/566d9426d122d86c.
Report an issue: GitHub.