SeleniumHQ/selenium · error · TypeError

button must be a positive integer or one of #{BUTTONS.keys},

Error message

button must be a positive integer or one of #{BUTTONS.keys}, not #{button.class}

What it means

Raised as TypeError by PointerPress#assert_button when button is neither a Symbol nor an Integer (the case/else branch). The message lists the accepted Symbol keys (BUTTONS.keys) and notes an Integer is also valid, then shows the offending value's class.

Source

Thrown at rb/lib/selenium/webdriver/common/interactions/pointer_press.rb:73

        private

        def assert_source(source)
          raise TypeError, "#{source.type} is not a valid input type" unless source.is_a? PointerInput
        end

        def assert_button(button)
          case button
          when Symbol
            raise ArgumentError, "#{button} is not a valid button!" unless BUTTONS.key? button

            BUTTONS[button]
          when Integer
            raise ArgumentError, 'Button number cannot be negative!' if button.negative?

            button
          else
            raise TypeError, "button must be a positive integer or one of #{BUTTONS.keys}, not #{button.class}"
          end
        end

        def assert_direction(direction)
          raise ArgumentError, "#{direction.inspect} is not a valid button direction" unless DIRECTIONS.key? direction

          DIRECTIONS[direction]
        end
      end # PointerPress
    end # Interactions
  end # WebDriver
end # Selenium

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Pass a Symbol (:left/:middle/:right/...) or a non-negative Integer.
  2. Coerce from config: button = config_string.match?(/^\d+$/) ? config_string.to_i : config_string.to_sym, then verify it is accepted.

Example fix

# before
driver.action.pointer_down('left').perform # => TypeError: button must be a positive integer or one of [:left, ...], not String

# after
driver.action.pointer_down(:left).perform
Defensive patterns

Strategy: type-guard

Validate before calling

case button
when String then button = button.match?(/\A-?\d+\z/) ? button.to_i : button.to_sym
when Float then button = button.to_i
end
driver.action.pointer_down(button).perform

Type guard

def button_arg?(b)
  b.is_a?(Symbol) || (b.is_a?(Integer) && !b.negative?)
end

Prevention

When it happens

Trigger: Passing pointer_down/pointer_up (or PointerPress.new) a value of an unsupported type: a String ('left'), a Float (0.0), nil, or an Object. The case statement only matches Symbol and Integer.

Common situations: Reading a button from JSON/YAML config as a string and not converting; passing nil where a button is required; mixing Float (0.0) with Integer expectations.

Related errors


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