SeleniumHQ/selenium · error · Error

Argument to isShown must be of type Element

Error message

Argument to isShown must be of type Element

What it means

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.

Source

Thrown at javascript/atoms/dom.js:462

  var parent = bot.dom.getParentElement(elem);
  return parent ? bot.dom.getCascadedStyle_(parent, styleName) : null;
};


/**
 * Extracted code from bot.dom.isShown.
 *
 * @param {!Element} elem The element to consider.
 * @param {boolean} ignoreOpacity Whether to ignore the element's opacity
 *     when determining whether it is shown.
 * @param {function(!Element):boolean} displayedFn a function that's used
 *     to tell if the chain of ancestors or descendants are all shown.
 * @return {boolean} Whether or not the element is visible.
 * @private
 */
bot.dom.isShown_ = function (elem, ignoreOpacity, displayedFn) {
  if (!bot.dom.isElement(elem)) {
    throw new Error('Argument to isShown must be of type Element');
  }

  // By convention, BODY element is always shown: BODY represents the document
  // and even if there's nothing rendered in there, user can always see there's
  // the document.
  if (bot.dom.isElement(elem, goog.dom.TagName.BODY)) {
    return true;
  }

  // Option or optgroup is shown iff enclosing select is shown (ignoring the
  // select's opacity).
  if (bot.dom.isElement(elem, goog.dom.TagName.OPTION) ||
    bot.dom.isElement(elem, goog.dom.TagName.OPTGROUP)) {
    var select = /**@type {Element}*/ (goog.dom.getAncestor(elem, function (e) {
      return bot.dom.isElement(e, goog.dom.TagName.SELECT);
    }));
    return !!select && bot.dom.isShown_(select, true, displayedFn);
  }

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Verify the node is an Element before calling isShown: use bot.dom.isElement(node) (or node.nodeType === 1) as a gate.
  2. If you selected a Text node via XPath text(), re-target the parent element (e.g. /.. axis) so you pass an Element.
  3. If staleness is the cause, re-find the element and confirm document.contains(elem) before retrying the visibility check.
  4. Ensure cross-frame element handles are resolved to their actual Element, not the frame Document or a wrapper.

Example fix

// before
var node = document.evaluate('//text()', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
bot.dom.isShown_(node, false, displayedFn); // throws: node is a Text node

// after
var elem = node.nodeType === 1 ? node : node.parentElement;
if (bot.dom.isElement(elem)) {
  bot.dom.isShown_(elem, false, displayedFn);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!elem || elem.nodeType !== 1) {
  throw new TypeError('isShown requires a DOM Element, got: ' + (elem && elem.nodeType))
}

Type guard

function isDomElement(node) {
  return node != null && node.nodeType === 1 && node instanceof Element
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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