{"record":{"id":"aeeee7bd0221d8ce","repo":"SeleniumHQ/selenium","slug":"invalid-drag-target-must-specify-a-webelement-or","errorCode":null,"errorMessage":"Invalid drag target; must specify a WebElement or {x, y} offset","messagePattern":"Invalid drag target; must specify a WebElement or (.+?) offset","errorType":"validation","errorClass":"InvalidArgumentError","httpStatus":400,"severity":"error","filePath":"javascript/selenium-webdriver/lib/input.js","lineNumber":942,"sourceCode":"   * 1.  Move to the center of the `from` element (element to be dragged).\n   * 2.  Press the left mouse button.\n   * 3.  If the `to` target is a {@linkplain ./webdriver.WebElement WebElement},\n   *     move the mouse to its center. Otherwise, move the mouse by the\n   *     specified offset.\n   * 4.  Release the left mouse button.\n   *\n   * @param {!./webdriver.WebElement} from The element to press the left mouse\n   *     button on to start the drag.\n   * @param {(!./webdriver.WebElement|{x: number, y: number})} to Either another\n   *     element to drag to (will drag to the center of the element), or an\n   *     object specifying the offset to drag by, in pixels.\n   * @return {!Actions} a self reference.\n   */\n  dragAndDrop(from, to) {\n    // Do not require up top to avoid a cycle that breaks static analysis.\n    const { WebElement } = require('./webdriver')\n    if (!(to instanceof WebElement) && (!to || typeof to.x !== 'number' || typeof to.y !== 'number')) {\n      throw new InvalidArgumentError('Invalid drag target; must specify a WebElement or {x, y} offset')\n    }\n\n    this.move({ origin: from }).press()\n    if (to instanceof WebElement) {\n      this.move({ origin: to })\n    } else {\n      this.move({ x: to.x, y: to.y, origin: Origin.POINTER })\n    }\n    return this.release()\n  }\n\n  /**\n   * Releases all keys, pointers, and clears internal state.\n   *\n   * @return {!Promise<void>} a promise that will resolve when finished\n   *     clearing all action state.\n   */\n  clear() {","sourceCodeStart":924,"sourceCodeEnd":960,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/javascript/selenium-webdriver/lib/input.js#L924-L960","documentation":"Thrown by Actions.dragAndDrop() when the `to` argument is neither a WebElement nor a plain object with numeric x and y properties. The validation runs synchronously before any pointer action is emitted, so no partial input sequence is sent. It is an InvalidArgumentError (400 invalid argument).","triggerScenarios":"Calling actions.dragAndDrop(from, undefined), dragAndDrop(from, null), dragAndDrop(from, {x: '5', y: 6}) (string coordinate), dragAndDrop(from, {x: 5}) (missing y), or passing a non-WebElement element-like object (e.g. a plain locator). A valid WebElement or {x:number, y:number} passes.","commonSituations":"Reading a target from a config/JSON where numbers arrive as strings; passing a DOM element handle from another framework instead of a selenium WebElement; typo'ing the coordinate object keys (e.g. {X, Y}); assuming the second arg is optional.","solutions":["Pass a WebElement: dragAndDrop(srcEl, destEl).","Pass numeric offsets: dragAndDrop(srcEl, {x: 10, y: 20}) where both are JS numbers.","Coerce config-supplied values: {x: Number(cfg.dx), y: Number(cfg.dy)} and verify !isNaN before calling.","If you only have a selector, resolve it to a WebElement first with driver.findElement(by).","Confirm the object is a selenium WebElement (instanceof webdriver.WebElement), not a bare handle."],"exampleFix":"// before\nconst cfg = JSON.parse(raw);\nawait driver.actions().dragAndDrop(src, cfg.offset); // throws if dx/dy are strings\n\n// after\nconst offset = { x: Number(cfg.offset.x), y: Number(cfg.offset.y) };\nif (Number.isNaN(offset.x) || Number.isNaN(offset.y)) throw new Error('bad offset');\nawait driver.actions().dragAndDrop(src, offset);","handlingStrategy":"type-guard","validationCode":"function validateDragTarget(to, WebElement) {\n  const isOffset =\n    to && typeof to === 'object' &&\n    typeof to.x === 'number' && typeof to.y === 'number' &&\n    Number.isFinite(to.x) && Number.isFinite(to.y);\n  if (!(to instanceof WebElement) && !isOffset) {\n    throw new Error('drag target must be WebElement or {x:number,y:number}');\n  }\n}","typeGuard":"function isWebElementOrOffset(to, WebElement) {\n  return (\n    to instanceof WebElement ||\n    (!!to && typeof to.x === 'number' && typeof to.y === 'number')\n  );\n}","tryCatchPattern":"try {\n  await driver.actions().dragAndDrop(src, target).perform();\n} catch (e) {\n  if (e.name === 'InvalidArgumentError' && /drag target/i.test(e.message)) {\n    // coerce numeric strings then retry\n    target = { x: Number(target.x), y: Number(target.y) };\n    await driver.actions().dragAndDrop(src, target).perform();\n  } else throw e;\n}","preventionTips":["Coerce config-loaded coordinates with Number() and check Number.isFinite before calling.","Keep WebElement imports from webdriver so instanceof checks work.","Never assume the second argument is optional."],"tags":["actions","drag-and-drop","validation","invalid-argument"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}