{"record":{"id":"d29de4a72ce13332","repo":"SeleniumHQ/selenium","slug":"action-inspect-is-not-a-valid-action","errorCode":null,"errorMessage":"#{action.inspect} is not a valid action","messagePattern":"#(.+?) is not a valid action","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"rb/lib/selenium/webdriver/common/interactions/input_device.rb","lineNumber":41,"sourceCode":"  module WebDriver\n    module Interactions\n      #\n      # Superclass for the input device sources\n      # Manages Array of Interaction instances for the device\n      #\n      # @api private\n      #\n\n      class InputDevice\n        attr_reader :name, :actions, :type\n\n        def initialize(name = nil)\n          @name = name || SecureRandom.uuid\n          @actions = []\n        end\n\n        def add_action(action)\n          raise TypeError, \"#{action.inspect} is not a valid action\" unless action.class < Interaction\n\n          @actions << action\n        end\n\n        def clear_actions\n          @actions.clear\n        end\n\n        def create_pause(duration = 0)\n          add_action(Pause.new(self, duration))\n        end\n\n        def encode\n          {type: type, id: name, actions: @actions.map(&:encode)} unless @actions.empty?\n        end\n      end # InputDevice\n    end # Interactions\n  end # WebDriver","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/rb/lib/selenium/webdriver/common/interactions/input_device.rb#L23-L59","documentation":"Raised as TypeError by InputDevice#add_action when the supplied object's class is not a descendant of Interaction (action.class < Interaction returns false/nil). InputDevice is @api private and underpins PointerInput / KeyInput / WheelInput / NoneInput; the guard ensures only well-formed Interaction subclasses enter the action list that gets encoded to the W3C actions payload.","triggerScenarios":"Calling input_device.add_action(obj) where obj is anything other than an instance of an Interaction subclass (Pause, PointerMove, PointerPress, PointerCancel, TypingInteraction, Scroll). E.g. passing a Hash, a Symbol, or a plain object.","commonSituations":"Only hit by code that hand-builds action devices instead of using the public ActionBuilder / driver.action DSL. Typically a custom ActionBuilder extension or a copy-paste that passes the wrong object to add_action.","solutions":["Use the public action DSL (driver.action.move_to(...).click.perform) instead of touching InputDevice#add_action directly.","If you must extend, ensure the object subclasses Selenium::WebDriver::Interactions::Interaction and is constructed with a valid source before being added."],"exampleFix":"# before\npointer.add_action({type: 'pointerDown', button: 0}) # => TypeError: {:type=>...} is not a valid action\n\n# after\npointer.add_action(Selenium::WebDriver::Interactions::PointerPress.new(pointer, :down, :left))","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"# Ensure only Interaction subclasses reach add_action\ndef interaction?(obj)\n  obj.is_a?(Selenium::WebDriver::Interactions::Interaction)\nend\n\npointer.add_action(obj) if interaction?(obj)","tryCatchPattern":null,"preventionTips":["Prefer the public driver.action DSL over hand-building InputDevice actions.","When extending ActionBuilder, only ever pass Interaction subclasses to add_action."],"tags":["interactions","action-builder","typecheck","internal-api","ruby"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}