alibaba/page-agent · error · Error
Element at index ${index} does not have a reference
Error message
Element at index ${index} does not have a reference What it means
Thrown when the interactive node exists in the selector map but its ref (live HTMLElement reference) is null or missing. The DOM tree keeps lightweight nodes with a back-reference to the real element; a missing ref means the node was serialized/detached or the element was removed from the document since indexing. The library refuses to operate on a node it cannot resolve to a real element.
Source
Thrown at packages/page-controller/src/actions.ts:34
waitFor,
} from './utils'
/**
* 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()View on GitHub (pinned to d02db1ee7c)
Solutions
- Re-index with updateTree() and immediately perform the action on the fresh tree
- Do not serialize or structuredClone the selector map/nodes; keep actions in the same context where indexing happened
- If the element is genuinely gone, re-observe and choose an equivalent element
- Reduce the delay between observation and action on dynamic pages
Example fix
// before await controller.inputText(7, 'hello') // node.ref === null // after await controller.updateTree() await controller.inputText(7, 'hello') // fresh refs
Defensive patterns
Strategy: retry
Try / catch
try { await controller.inputText(i, text) } catch (e) { if (String(e).includes('does not have a reference')) { await controller.updateTree(); await controller.inputText(i, text) } else throw e } Prevention
- Keep indexing and actions in the same JS context; never structuredClone or message-pass the selector map
- Minimize delay between updateTree() and actions on dynamic pages
- Re-index after SPA route changes or list re-renders
When it happens
Trigger: Element was removed from the DOM (SPA rerender, route change, list virtualization) between updateTree() and the action; tree data was structured-cloned or serialized across contexts (extension content script vs background), dropping the live ref; corrupted/partial indexing.
Common situations: Browser extension passing the dom tree through message passing which strips element references; fast-changing pages where nodes detach quickly; memory-pressure cleanup clearing refs.
Related errors
- DOM tree not indexed yet. Can not perform actions on element
- No interactive element found at index ${index}
- Element at index ${index} is not an HTMLElement
- 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/4948cb085680c571.
Report an issue: GitHub.