SeleniumHQ/selenium · error · ArgumentError
expected #{arg.inspect}:#{arg.class} to respond to #shift
Error message
expected #{arg.inspect}:#{arg.class} to respond to #shift What it means
Raised by SearchContext#extract_args (private) when find_element or find_elements is called with exactly one argument that does not respond to the :shift method (i.e., not a Hash or Array-like object). The method expects either two positional args (how, what) or a single Hash/Array that can be shifted into a key-value or [key, value] pair.
Source
Thrown at rb/lib/selenium/webdriver/common/search_context.rb:99
how, what = extract_args(args)
by = SearchContext.finders[how.to_sym]
raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
bridge.find_elements_by by, what, ref
end
private
def extract_args(args)
case args.size
when 2
args
when 1
arg = args.first
unless arg.respond_to?(:shift)
raise ArgumentError,
"expected #{arg.inspect}:#{arg.class} to respond to #shift"
end
# this will be a single-entry hash, so use #shift over #first or #[]
arr = arg.dup.shift
raise ArgumentError, "expected #{arr.inspect} to have 2 elements" unless arr.size == 2
arr
else
raise ArgumentError, "wrong number of arguments (#{args.size} for 2)"
end
end
end # SearchContext
end # WebDriver
end # Selenium
View on GitHub (pinned to aa36b38e69)
Solutions
- Pass two arguments: find_element(:css, '#my-id').
- Or pass a single Hash: find_element(css: '#my-id').
- Check that the variable holding your locator options is not nil before calling find_element.
Example fix
// before element = driver.find_element(:css) # missing the locator value // after element = driver.find_element(:css, '#submit')
Defensive patterns
Strategy: type-guard
Validate before calling
def safe_find(driver, *args)
if args.size == 1 && !args.first.respond_to?(:shift)
raise ArgumentError, "Single argument must be a Hash or Array, got #{args.first.class}"
end
driver.find_element(*args)
end Type guard
def valid_find_arg?(arg) arg.respond_to?(:shift) end
Try / catch
begin
driver.find_element(locator)
rescue ArgumentError => e
raise unless e.message.include?('to respond to #shift')
# locator is not a Hash; wrap it
driver.find_element(*Array(locator))
end Prevention
- Standardize on the two-argument form find_element(how, what) to avoid Hash/Array ambiguity.
- If building locators dynamically, type-check before calling find_element.
- Add RuboCop or custom linters to catch bare single-argument find_element calls.
When it happens
Trigger: Calling find_element('css') with only a strategy and no locator value. Calling find_element(42) or find_element(nil) with a non-Hash, non-Array argument. Calling find_element(SomeObject.new) with an arbitrary object.
Common situations: Forgot the second argument (the locator value). Passing a driver or element object as the sole argument by mistake. Variable interpolation producing nil where a Hash was expected.
Related errors
- cannot find element by #{how.inspect}
- expected #{arr.inspect} to have 2 elements
- wrong number of arguments (#{args.size} for 2)
- incompatible proxy type #{type.inspect} (already set to #{@t
- cannot find elements by #{how.inspect}
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/7b075cd7fdcbbfba.
Report an issue: GitHub.