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
- 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.
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
- 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.
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
- Argument to isShown must be of type Element
- Element does not have any client rects
- Expected input and output file paths
- Expected input and output file paths
- Unexpected compiled output format. Expected it to start with
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/9f45343feefe5157.
Report an issue: GitHub.