teamcapybara/capybara · error · ArgumentError
Unknown keys type
Error message
Unknown keys type
What it means
Raised by _send_keys in the Selenium Safari node when a value sent to an element is not a String, Symbol, or Array. The dispatcher case-matches those three types and everything else (Integer, Float, nil, Hash) falls into the else branch with 'Unknown keys type'.
Source
Thrown at lib/capybara/selenium/nodes/safari_node.rb:108
private
def _send_keys(keys, actions = browser_action, down_keys = ModifierKeysStack.new)
case keys
when *MODIFIER_KEYS
down_keys.press(keys)
actions.key_down(keys)
when String
keys = keys.upcase if down_keys&.include?(:shift)
actions.send_keys(keys)
when Symbol
actions.send_keys(keys)
when Array
down_keys.push
keys.each { |sub_keys| _send_keys(sub_keys, actions, down_keys) }
down_keys.pop.reverse_each { |key| actions.key_up(key) }
else
raise ArgumentError, 'Unknown keys type'
end
actions
end
MODIFIER_KEYS = %i[control left_control right_control
alt left_alt right_alt
shift left_shift right_shift
meta left_meta right_meta
command].freeze
end
View on GitHub (pinned to 15b5fdb76e)
Solutions
- Convert before sending: find('#pin').send_keys(pin.to_s)
- Send special keys as symbols: send_keys('text', :enter) or send_keys([:shift, 'a'])
- Centralize input in a helper that coerces: def type_into(el, val) el.send_keys(String(val)) end
Example fix
# before
find('#pin').set(1234)
# after
find('#pin').set(1234.to_s) Defensive patterns
Strategy: type-guard
Validate before calling
def valid_keys?(k)
case k
when String, Symbol then true
when Array then k.all? { |sub| valid_keys?(sub) }
else false
end
end
find('#pin').send_keys(value) if valid_keys?(value) Type guard
def coerce_keys(k)
case k
when String, Symbol, Array then k
else k.to_s
end
end
find('#pin').send_keys(coerce_keys(user_pin)) Try / catch
begin el.send_keys(value) rescue ArgumentError => e raise unless e.message == 'Unknown keys type' el.send_keys(value.to_s) end
Prevention
- Call .to_s on any external or numeric data before send_keys
- Use Selenium key symbols (:enter, :shift) for special keys, never integer codes
- Route all keyboard input through one coercion helper
When it happens
Trigger: find('#pin').send_keys(1234) or el.set(42) on the selenium_safari driver; send_keys(nil); arrays mixing invalid members such as [1, :enter]; passing keycodes as integers copied from other driver APIs.
Common situations: Passing numeric values from factories, Faker, or Cucumber step tables straight to send_keys; porting specs from rack_test (which stringifies input) to selenium; translating Java/JS sendKeys examples that use char codes literally.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- You may only upload files: #{local_file.inspect}
- Chromedriver 75+ defaults to W3C mode. Please upgrade to chr
- Window size not stable within #{seconds} seconds.
- Locator #{locator.class}:#{locator.inspect} for selector #{n
AI-assisted analysis of teamcapybara/capybara@15b5fdb76e (2026-08-21).
Data as JSON: /api/errors/1fbd9115cf2a93b9.
Report an issue: GitHub.