alibaba/page-agent · error · Error
Element at index ${index} is not an HTMLElement
Error message
Element at index ${index} is not an HTMLElement What it means
The indexed node's ref resolved to something that is not an HTMLElement (e.g., an SVGElement, a text node, or a non-element object). All actions (click, input, select) require a real HTMLElement with the full element API, so the library guards the type before acting. It usually indicates an unexpected object ended up in the selector map or cross-realm elements from another frame/document.
Source
Thrown at packages/page-controller/src/actions.ts:38
* Get the HTMLElement by index from a selectorMap.
* @private Internal method, subject to change at any time.
*/
export function getElementByIndex(
selectorMap: Map<number, InteractiveElementDomNode>,
index: number
): HTMLElement {
const interactiveNode = selectorMap.get(index)
if (!interactiveNode) {
throw new Error(`No interactive element found at index ${index}`)
}
const element = interactiveNode.ref
if (!element) {
throw new Error(`Element at index ${index} does not have a reference`)
}
if (!isHTMLElement(element)) {
throw new Error(`Element at index ${index} is not an HTMLElement`)
}
return element
}
let lastClickedElement: HTMLElement | null = null
function blurLastClickedElement() {
if (lastClickedElement) {
lastClickedElement.dispatchEvent(new PointerEvent('pointerout', { bubbles: true }))
lastClickedElement.dispatchEvent(new PointerEvent('pointerleave', { bubbles: false }))
lastClickedElement.dispatchEvent(new MouseEvent('mouseout', { bubbles: true }))
lastClickedElement.dispatchEvent(new MouseEvent('mouseleave', { bubbles: false }))
lastClickedElement.blur()
lastClickedElement = null
}
}
View on GitHub (pinned to d02db1ee7c)
Solutions
- Check what sits at that index via getSimplifiedHTML() and pick a real HTML element
- If testing, ensure the same HTMLElement realm/global is used (single jsdom instance, single library copy)
- Re-index after navigation so refs come from the current document
- Report upstream if a legitimately interactive SVG is misclassified and blocks your flow
Example fix
// before await controller.clickElement(3) // ref is SVGElement // after await controller.updateTree() // target an actual HTML element index, e.g. the parent <button>: await controller.clickElement(2)
Defensive patterns
Strategy: type-guard
Type guard
const el = controller.element?.(i); if (el instanceof HTMLElement) { /* safe to act */ } Try / catch
try { await controller.clickElement(i) } catch (e) { if (String(e).includes('is not an HTMLElement')) { /* pick a different index */ } else throw e } Prevention
- Prefer indexes of real HTML controls over SVG/graphics nodes
- In tests, use a single DOM library instance/realm
- Re-index after cross-frame or cross-document navigation
When it happens
Trigger: The indexed element is an SVG element or other non-HTML element; the ref came from a different document/iframe realm so instanceof HTMLElement fails; a mock or test double was injected into the tree.
Common situations: Pages with SVG-heavy UIs where an SVG node got flagged interactive; jsdom/test environments where HTMLElement globals differ between copies of the library; cross-realm elements from iframes.
Related errors
- DOM tree not indexed yet. Can not perform actions on element
- No interactive element found at index ${index}
- Element at index ${index} does not have a reference
- Element is not an input, textarea, or contenteditable
- Element is not a select element
AI-assisted analysis of alibaba/page-agent@d02db1ee7c (2026-08-28).
Data as JSON: /api/errors/e424dd8764981474.
Report an issue: GitHub.