jackwener/OpenCLI · error
Element not found: ref=${ref}
Error message
Element not found: ref=${ref} What it means
scrollToRefJs builds an in-page script that resolves an element by its snapshot ref attribute (data-opencli-ref or data-ref) and scrolls it into view. If no element with that ref exists in the current document, the injected script throws 'Element not found: ref=<ref>'.
Source
Thrown at src/browser/dom-snapshot.ts:85
/** Previous snapshot hash set (JSON array of hashes) for diff marking (default null) */
previousHashes?: string | null;
}
// ─── Utility JS Generators ───────────────────────────────────────────
/**
* Generate JS to scroll to an element identified by data-opencli-ref.
* Completes the snapshot→action loop: snapshot identifies `[3]<button>`,
* caller can then `scrollToRef('3')` to bring it into view.
*/
export function scrollToRefJs(ref: string): string {
const safeRef = JSON.stringify(ref);
return `
(() => {
const ref = ${safeRef};
const el = document.querySelector('[data-opencli-ref="' + ref + '"]')
|| document.querySelector('[data-ref="' + ref + '"]');
if (!el) throw new Error('Element not found: ref=' + ref);
el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
return { scrolled: true, tag: el.tagName.toLowerCase(), text: (el.textContent || '').trim().slice(0, 80) };
})()
`.trim();
}
/**
* Generate JS to extract all form field values from the page.
* Returns structured JSON: { forms: [{ id, action, fields: [{ tag, type, name, value, ... }] }] }
*/
export function getFormStateJs(): string {
return `
(() => {
const result = { forms: [], orphanFields: [] };
// Collect all forms
for (const form of document.forms) {
const formData = {View on GitHub (pinned to 49907e53dc)
Solutions
- Re-take the DOM snapshot to obtain fresh refs and retry with the new ref
- Verify you are targeting the same tab/frame the snapshot came from
- Guard the call in try/catch and fall back to re-snapshotting when the ref is stale
Example fix
// before await page.scroll(refFromOldSnapshot); // after const snap = await page.snapshot(); await page.scroll(snap.refOfElement);
Defensive patterns
Strategy: try-catch
Validate before calling
const exists = await page.evaluate(`!!document.querySelector('[data-opencli-ref="${ref}"]')`);
if (!exists) await page.snapshot(); // refresh refs first Type guard
function isRefLive(exists: boolean): boolean { return exists === true; } Try / catch
try { await page.scroll(ref); }
catch (e) {
if (String(e.message).startsWith('Element not found')) {
await page.snapshot();
ref = /* fresh ref */;
await page.scroll(ref);
} else throw e;
} Prevention
- Always use refs from the most recent snapshot
- Re-snapshot after navigation or DOM mutations
- Confirm the same tab/frame used for the snapshot
When it happens
Trigger: Calling scroll (via js/scrollToRefJs) with a ref string that does not match any element carrying data-opencli-ref/data-ref — typically a stale ref from a previous snapshot or a snapshot taken in a different frame/page.
Common situations: The page navigated or re-rendered after the DOM snapshot was taken, invalidating refs; using a ref from another tab/iframe; typo in the ref value.
Related errors
- Element not found: ${safeRef}
- No resolved element
- Failed to extract Booking.com cards: ${err?.message || err}
- coupang add-to-cart evaluation failed: ${error?.message || e
- coupang search
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/526b93ceaecc3e26.
Report an issue: GitHub.