{"record":{"id":"bf5a90d96d660b77","repo":"alibaba/page-agent","slug":"dom-tree-not-indexed-yet-can-not-perform-actions","errorCode":null,"errorMessage":"DOM tree not indexed yet. Can not perform actions on elements.","messagePattern":"DOM tree not indexed yet\\. Can not perform actions on elements\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/page-controller/src/PageController.ts","lineNumber":237,"sourceCode":"\t}\n\n\t/**\n\t * Clean up all element highlights\n\t */\n\tasync cleanUpHighlights(): Promise<void> {\n\t\tconsole.log('[PageController] cleanUpHighlights')\n\t\tdom.cleanUpHighlights()\n\t}\n\n\t// ======= Element Actions =======\n\n\t/**\n\t * Ensure the tree has been indexed before any index-based operation.\n\t * Throws if updateTree() hasn't been called yet.\n\t */\n\tprivate assertIndexed(): void {\n\t\tif (!this.isIndexed) {\n\t\t\tthrow new Error('DOM tree not indexed yet. Can not perform actions on elements.')\n\t\t}\n\t}\n\n\t/**\n\t * Click element by index\n\t */\n\tasync clickElement(index: number): Promise<ActionResult> {\n\t\ttry {\n\t\t\tthis.assertIndexed()\n\t\t\tconst element = getElementByIndex(this.selectorMap, index)\n\t\t\tconst elemText = this.elementTextMap.get(index)\n\t\t\tawait clickElement(element)\n\n\t\t\t// Handle links that open in new tabs\n\t\t\tif (isAnchorElement(element) && element.target === '_blank') {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `✅ Clicked element (${elemText ?? index}). ⚠️ Link opened in a new tab.`,","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/alibaba/page-agent/blob/d02db1ee7c41f5315beda88bab2fe935c580f662/packages/page-controller/src/PageController.ts#L219-L255","documentation":"PageController throws this error when an index-based action (clickElement, inputText, selectOption, scroll, scrollHorizontally) is called before updateTree() has built and indexed the DOM tree. Elements are addressed by numeric indexes produced by the indexing pass, so without it there is no selector map to resolve indexes against. It is a guard against operating on a stale or nonexistent snapshot.","triggerScenarios":"Calling pageController.clickElement(5), inputText, selectOption, scroll, or scrollHorizontally before ever awaiting updateTree(); or after the tree was invalidated/re-indexed asynchronously while an action is already in flight.","commonSituations":"Running actions immediately after constructing PageController; forgetting that updateTree() is async and not awaiting it; a PageAgent loop that skips the initial observation step; calling scroll() first because it seems index-free but still goes through assertIndexed.","solutions":["Await pageController.updateTree() once (and after DOM changes) before any index-based action: await pageController.updateTree(); await pageController.clickElement(5)","Re-index between steps in an agent loop (the DOM changes after clicks/inputs)","Check pageController.isIndexed before acting if state is uncertain","Pass valid indexes obtained from getSimplifiedHTML()/getPageInfo() of the same snapshot"],"exampleFix":"// before\nawait controller.clickElement(3) // throws: tree not indexed\n\n// after\nawait controller.updateTree()\nawait controller.clickElement(3)","handlingStrategy":"validation","validationCode":"if (!await controller.isIndexed) { await controller.updateTree() } // then call the action","typeGuard":null,"tryCatchPattern":"try { await controller.clickElement(i) } catch (e) { if (e instanceof Error && e.message.includes('not indexed')) { await controller.updateTree(); await controller.clickElement(i) } else throw e }","preventionTips":["Always await updateTree() immediately after constructing PageController","Re-index after any action that mutates the DOM before the next index-based action","Treat updateTree + observe + act as one atomic step in agent loops"],"tags":["dom","page-controller","index","state-not-initialized"],"backgroundTag":"invalid-state-not-initialized","analyzedSha":"d02db1ee7c41f5315beda88bab2fe935c580f662","analyzedAt":"2026-08-28T19:39:48.634Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}