jackwener/OpenCLI · error
DOM node not found
Error message
DOM node not found
What it means
clickWithQuads resolves the CSS selector via CDP DOM.querySelectorAll against the document. If no matching nodes are returned it throws 'DOM node not found' before attempting quad-based clicking.
Source
Thrown at src/browser/page.ts:370
// Scroll element into view first
await this.evaluate(`
(() => {
const el = document.querySelector('[data-opencli-ref="' + ${safeRef} + '"]');
if (el) el.scrollIntoView({ behavior: 'instant', block: 'center' });
return !!el;
})()
`);
try {
// Find DOM node via CDP
const doc = await this.cdp('DOM.getDocument', {}) as { root: { nodeId: number } };
const result = await this.cdp('DOM.querySelectorAll', {
nodeId: doc.root.nodeId,
selector: cssSelector,
}) as { nodeIds: number[] };
if (!result.nodeIds?.length) throw new Error('DOM node not found');
const nodeId = result.nodeIds[0];
// Try getContentQuads first (precise for inline elements)
try {
const quads = await this.cdp('DOM.getContentQuads', { nodeId }) as { quads: number[][] };
if (quads.quads?.length) {
const q = quads.quads[0];
const cx = (q[0] + q[2] + q[4] + q[6]) / 4;
const cy = (q[1] + q[3] + q[5] + q[7]) / 4;
await this.nativeClick(Math.round(cx), Math.round(cy));
return;
}
} catch { /* fallthrough */ }
// Try getBoxModel
try {
const box = await this.cdp('DOM.getBoxModel', { nodeId }) as { model: { content: number[] } };View on GitHub (pinned to 49907e53dc)
Solutions
- Verify the selector matches in the page console: document.querySelectorAll(sel).length
- Wait for the element to appear (e.g. waitForSelector/polling) before clicking
- Use a snapshot ref instead of a raw CSS selector
- Ensure the element is not inside a shadow root or iframe the CDP document query misses
Example fix
// before
await page.clickWithQuads('.submit-btn', ...);
// after
await page.waitForSelector('.submit-btn');
await page.clickWithQuads('.submit-btn', ...); Defensive patterns
Strategy: validation
Validate before calling
const n = await page.evaluate(`document.querySelectorAll(${JSON.stringify(sel)}).length`);
if (!n) throw new Error(`selector ${sel} matches nothing`); Type guard
function hasNodes(r: { nodeIds?: number[] } | null): r is { nodeIds: number[] } {
return Array.isArray(r?.nodeIds) && r.nodeIds.length > 0;
} Try / catch
try { await page.clickWithQuads(sel, ...); }
catch (e) {
if (e.message === 'DOM node not found') {
await page.waitForSelector(sel);
await page.clickWithQuads(sel, ...);
} else throw e;
} Prevention
- Wait for element presence before clicking
- Validate selectors in the page console
- Avoid selectors targeting iframe/shadow-DOM content for document-level queries
When it happens
Trigger: Calling page.clickWithQuads(selector, ...) with a CSS selector that matches zero elements in the current document at CDP level.
Common situations: Selector typo; element rendered after an async load/spinner; element inside an iframe or shadow DOM not covered by document.querySelectorAll; page navigated between snapshot and click.
Related errors
- Could not locate Midjourney ${slotLabel} slot after upload
- No element found matching selector: ${query}
- NO_DIALOG
- amazon ${action} navigation lost the current browser target
- Could not find Antigravity input box
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/43ad07f45de30fd7.
Report an issue: GitHub.