SeleniumHQ/selenium · error · ArgumentError

expected #{arr.inspect} to have 2 elements

Error message

expected #{arr.inspect} to have 2 elements

What it means

Raised by SearchContext#extract_args when a single Hash argument is passed to find_element/find_elements but the shifted key-value pair does not yield exactly 2 elements. This is an internal consistency check after calling Hash#shift on a duplicated hash; it should always produce a [key, value] pair of size 2. Encountering this error implies the argument was an Array or custom object whose #shift returned something unexpected.

Source

Thrown at rb/lib/selenium/webdriver/common/search_context.rb:105

      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

  1. Pass a well-formed two-element array: find_element([:css, '#my-id']).
  2. Or use the Hash form: find_element(css: '#my-id').
  3. Validate the locator structure before passing it if building dynamically.

Example fix

// before
strategy = [:css]
element = driver.find_element(strategy)  # only 1 element

// after
strategy = [:css, '#my-id']
element = driver.find_element(strategy)
Defensive patterns

Strategy: validation

Validate before calling

def build_locator(how, what)
  [how, what].tap do |arr|
    raise ArgumentError, 'Locator must have exactly 2 elements' unless arr.size == 2
  end
end

# usage: driver.find_element(build_locator(:css, '#id'))

Type guard

def valid_two_element_array?(arr)
  arr.is_a?(Array) && arr.size == 2
end

Try / catch

begin
  driver.find_element(locator)
rescue ArgumentError => e
  raise unless e.message.include?('to have 2 elements')
  raise ArgumentError, "Locator array malformed: #{locator.inspect}. Expected [strategy, value]."
end

Prevention

When it happens

Trigger: Passing a single Array like find_element([:css]) (size 1) instead of find_element([:css, '#id']) (size 2). Passing a custom object that responds to #shift but returns an array of size != 2. Passing an empty Hash find_element({}) where shift returns nil.

Common situations: Constructing a locator array dynamically and accidentally producing a malformed array. Passing a multi-key Hash (only the first key is used via shift, but if values are themselves arrays the size check can be confused).

Related errors


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