{"record":{"id":"12ec80de83dddaef","repo":"SeleniumHQ/selenium","slug":"move-to-requires-a-webelement","errorCode":null,"errorMessage":"move_to requires a WebElement","messagePattern":"move_to requires a WebElement","errorType":"validation","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"py/selenium/webdriver/common/actions/pointer_actions.py","lineNumber":89,"sourceCode":"        return self\n\n    def move_to(\n        self,\n        element,\n        x=0,\n        y=0,\n        width=None,\n        height=None,\n        pressure=None,\n        tangential_pressure=None,\n        tilt_x=None,\n        tilt_y=None,\n        twist=None,\n        altitude_angle=None,\n        azimuth_angle=None,\n    ):\n        if not isinstance(element, WebElement):\n            raise AttributeError(\"move_to requires a WebElement\")\n\n        self.source.create_pointer_move(\n            origin=element,\n            duration=self._duration,\n            x=int(x),\n            y=int(y),\n            width=width,\n            height=height,\n            pressure=pressure,\n            tangential_pressure=tangential_pressure,\n            tilt_x=tilt_x,\n            tilt_y=tilt_y,\n            twist=twist,\n            altitude_angle=altitude_angle,\n            azimuth_angle=azimuth_angle,\n        )\n        return self\n","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/py/selenium/webdriver/common/actions/pointer_actions.py#L71-L107","documentation":"`PointerActions.move_to` requires its first argument to be a `WebElement`. Passing anything else (a locator string, a Driver, a dict, None) raises `AttributeError` (note: semantically a TypeError, but raised as AttributeError). The pointer cannot move to a non-element target.","triggerScenarios":"`move_to(driver.find_element(...))` works, but `move_to(\"id=foo\")`, `move_to(By.ID)`, `move_to(None)`, or `move_to(locator_tuple)` all fail. Calling move_to on a result of a failed find that returned a falsy/empty value.","commonSituations":"Forgetting to call `find_element` and passing the locator. A stale or shadow-DOM lookup returning a non-WebElement. Mocking elements in tests with a fake object.","solutions":["Always pass the result of `driver.find_element(...)`: `move_to(driver.find_element(By.ID, \"foo\"))`.","Ensure the element was found before moving: guard with a find + None check.","For pointer-move to coordinates, use the lower-level pointer input API or ActionChains move_by_offset."],"exampleFix":"// before\nactions.move_to((By.ID, \"foo\"))  # AttributeError - passed a locator\n// after\nel = driver.find_element(By.ID, \"foo\")\nactions.move_to(el)","handlingStrategy":"type-guard","validationCode":"from selenium.webdriver.remote.webelement import WebElement\nel = driver.find_element(By.ID, \"foo\")\nassert isinstance(el, WebElement), \"move_to requires a WebElement\"\nactions.move_to(el)","typeGuard":"from selenium.webdriver.remote.webelement import WebElement\ndef is_webelement(value) -> bool:\n    return isinstance(value, WebElement)","tryCatchPattern":"try:\n    actions.move_to(target)\nexcept AttributeError:\n    # target was not a WebElement; find it first\n    actions.move_to(driver.find_element(By.ID, target))","preventionTips":["Always call find_element and pass its result, not the locator.","Type-hint move_to callers as (el: WebElement, ...).","Add a None check after find_element in flaky contexts."],"tags":["actions","pointer","webelement","attribute-error"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}