{"record":{"id":"9f45343feefe5157","repo":"SeleniumHQ/selenium","slug":"argument-to-isshown-must-be-of-type-element","errorCode":null,"errorMessage":"Argument to isShown must be of type Element","messagePattern":"Argument to isShown must be of type Element","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"javascript/atoms/dom.js","lineNumber":462,"sourceCode":"  var parent = bot.dom.getParentElement(elem);\n  return parent ? bot.dom.getCascadedStyle_(parent, styleName) : null;\n};\n\n\n/**\n * Extracted code from bot.dom.isShown.\n *\n * @param {!Element} elem The element to consider.\n * @param {boolean} ignoreOpacity Whether to ignore the element's opacity\n *     when determining whether it is shown.\n * @param {function(!Element):boolean} displayedFn a function that's used\n *     to tell if the chain of ancestors or descendants are all shown.\n * @return {boolean} Whether or not the element is visible.\n * @private\n */\nbot.dom.isShown_ = function (elem, ignoreOpacity, displayedFn) {\n  if (!bot.dom.isElement(elem)) {\n    throw new Error('Argument to isShown must be of type Element');\n  }\n\n  // By convention, BODY element is always shown: BODY represents the document\n  // and even if there's nothing rendered in there, user can always see there's\n  // the document.\n  if (bot.dom.isElement(elem, goog.dom.TagName.BODY)) {\n    return true;\n  }\n\n  // Option or optgroup is shown iff enclosing select is shown (ignoring the\n  // select's opacity).\n  if (bot.dom.isElement(elem, goog.dom.TagName.OPTION) ||\n    bot.dom.isElement(elem, goog.dom.TagName.OPTGROUP)) {\n    var select = /**@type {Element}*/ (goog.dom.getAncestor(elem, function (e) {\n      return bot.dom.isElement(e, goog.dom.TagName.SELECT);\n    }));\n    return !!select && bot.dom.isShown_(select, true, displayedFn);\n  }","sourceCodeStart":444,"sourceCodeEnd":480,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/javascript/atoms/dom.js#L444-L480","documentation":"bot.dom.isShown_ (the legacy Closure-based isShown atom in dom.js) requires its first argument to be a real DOM Element. It runs bot.dom.isElement(elem) at the top of the function and throws this literal error before doing any visibility work, because the entire algorithm (BODY short-circuit, OPTION/OPTGROUP handling, image-map resolution, opacity/overflow checks) assumes Element-level APIs (getClientRects, getComputedStyle, parent traversal). Passing a Text node, a Document, null/undefined, a detached wrapper, or a stale element reference from a frame that navigated away fails this guard. This atom backs Selenium's WebElement.isDisplayed() checks executed through the legacy injected-JS path.","triggerScenarios":"Calling bot.dom.isShown_ directly with a non-Element node (e.g. document.createTextNode('x'), document, a ShadowRoot, or an attribute Text node). Indirectly: the Selenium server injects isShown against an element whose underlying node is not an Element (a Text node selected via XPath text(), a document fragment, or a stale element handle whose page already navigated). Passing null/undefined because a findElement returned nothing and the result was forwarded without a null check.","commonSituations":"Locating a text node with an XPath like //text()[contains(.,'foo')] and then calling isDisplayed() on it. Shadow-DOM piercing where the resolved node is a ShadowRoot rather than its host element. Cross-frame element staleness after navigation, where the element handle resolves to a non-Element. Test frameworks forwarding a loosely-typed locator result into the visibility check.","solutions":["Verify the node is an Element before calling isShown: use bot.dom.isElement(node) (or node.nodeType === 1) as a gate.","If you selected a Text node via XPath text(), re-target the parent element (e.g. /.. axis) so you pass an Element.","If staleness is the cause, re-find the element and confirm document.contains(elem) before retrying the visibility check.","Ensure cross-frame element handles are resolved to their actual Element, not the frame Document or a wrapper."],"exampleFix":"// before\nvar node = document.evaluate('//text()', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;\nbot.dom.isShown_(node, false, displayedFn); // throws: node is a Text node\n\n// after\nvar elem = node.nodeType === 1 ? node : node.parentElement;\nif (bot.dom.isElement(elem)) {\n  bot.dom.isShown_(elem, false, displayedFn);\n}","handlingStrategy":"type-guard","validationCode":"if (!elem || elem.nodeType !== 1) {\n  throw new TypeError('isShown requires a DOM Element, got: ' + (elem && elem.nodeType))\n}","typeGuard":"function isDomElement(node) {\n  return node != null && node.nodeType === 1 && node instanceof Element\n}","tryCatchPattern":null,"preventionTips":["Gate every isShown call with bot.dom.isElement(elem) or nodeType === 1.","When selecting text nodes via XPath, resolve to the parent Element first.","Re-find elements after navigation to avoid stale/non-Element references.","Never forward findElement results without a null/type check."],"tags":["dom","visibility","isshown","type-validation","atoms"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}