SeleniumHQ/selenium · error · TypeError

#{num} is not a #{klass}

Error message

#{num} is not a #{klass}

What it means

Raised as TypeError by PointerEventProperties.assert_number when a pointer-event property value is non-nil but the wrong numeric type. The expected class is chosen from the VALID range: if the property's min is an Integer (tilt_x, tilt_y, twist) the value must be an Integer; otherwise (width, height, pressure, tangential_pressure, altitude_angle, azimuth_angle — min is a Float) any Numeric is accepted.

Source

Thrown at rb/lib/selenium/webdriver/common/interactions/pointer_event_properties.rb:52

        def process_opts
          raise ArgumentError, "Unknown options found: #{@opts.inspect}" unless (@opts.keys - VALID.keys).empty?

          VALID.each_with_object({}) do |(key, val), hash|
            next unless @opts.key?(key)

            name = val.keys.first
            values = val.values.first
            hash[name] = assert_number(@opts[key], values[:min], values[:max])
          end
        end

        private

        def assert_number(num, min, max = nil)
          return if num.nil?

          klass = min.is_a?(Integer) ? Integer : Numeric
          raise TypeError, "#{num} is not a #{klass}" unless num.is_a?(klass)

          raise ArgumentError, "#{num} is not greater than or equal to #{min}" if num < min

          raise ArgumentError, "#{num} is not less than or equal to #{max}" if max && num > max

          num
        end
      end # PointerEventProperties
    end # Interactions
  end # WebDriver
end # Selenium

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Convert the value to the expected type before passing: use .to_i for tilt_x/tilt_y/twist and .to_f for the Float-typed properties.
  2. For tilt_x/tilt_y/twist pass plain Integers (e.g. tilt_x: 45, not 45.0).
  3. If loading from config, coerce: Integer(val) for integer props, Float(val) for float props, with rescue for bad strings.

Example fix

# before
driver.action.pointer_down(:pen_contact, tilt_x: 45.0, twist: 90.5).perform # => TypeError: 45.0 is not an Integer

# after
driver.action.pointer_down(:pen_contact, tilt_x: 45, twist: 90).perform
Defensive patterns

Strategy: validation

Validate before calling

# Coerce to the expected type before passing
INTEGER_PROPS = %i[tilt_x tilt_y twist].freeze
def coerce(prop, val)
  return nil if val.nil?
  INTEGER_PROPS.include?(prop) ? Integer(val) : Float(val)
rescue ArgumentError
  raise "#{prop} value #{val.inspect} is not numeric"
end

driver.action.pointer_down(:pen_contact, tilt_x: coerce(:tilt_x, computed)).perform

Type guard

def numeric_for_prop?(prop, val)
  return true if val.nil?
  integer_prop = %i[tilt_x tilt_y twist].include?(prop)
  integer_prop ? val.is_a?(Integer) : val.is_a?(Numeric)
end

Prevention

When it happens

Trigger: Passing a Float where an Integer is required, e.g. tilt_x: 45.0 or twist: 90.5; passing a String like pressure: '0.5'; passing a Rational/Complex for a Float-typed property is fine (Numeric) but a String is not.

Common situations: Computing tilt/twist from trigonometry (returns Float) and feeding it directly; reading values from JSON/config as strings and not converting; mixing up which properties are integer-valued.

Related errors


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