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
- Pass a Symbol (:left/:middle/:right/...) or a non-negative Integer.
- 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
- Pass a Symbol or a non-negative Integer only — never a String, Float, or nil.
- Coerce config-derived button values (String) to Symbol/Integer before use.
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
- #{action.inspect} is not a valid action
- #{num} is not a #{klass}
- #{pointer.inspect} is not a valid pointer type
- #{source.type} is not a valid input type
- #{button} is not a valid button!
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/096167daf9978af0.
Report an issue: GitHub.