CloakHQ/CloakBrowser · error · Error
Element not found while scrolling into view
Error message
Element not found while scrolling into view
What it means
Inside humanScrollIntoView, getBox() resolves the element's bounding box (via the isolated-world snapshot). If it returns null at the initial lookup stage, the element could not be found/measured at all, so scrolling cannot proceed. This fires before any scrolling happens — it's the 'element doesn't exist (or has no box) at action time' case.
Source
Thrown at js/src/human/scroll.ts:98
getBox: () => Promise<T | null>,
cursorX: number,
cursorY: number,
cfg: HumanConfig,
): Promise<{ box: T; cursorX: number; cursorY: number; didScroll: boolean }> {
let viewport = page.viewportSize();
if (!viewport) {
const world = getWorld(page);
if (!world) throw new StealthWorldUnavailableError();
try {
viewport = await world.evaluate(VIEWPORT_JS);
} catch {
throw new StealthEvaluationError('<viewport>');
}
}
if (!viewport || !viewport.height) throw new Error('Viewport size not available');
let box = await getBox();
if (!box) throw new Error('Element not found while scrolling into view');
if (isInViewport(box, viewport.height, cfg)) {
return { box, cursorX, cursorY, didScroll: false };
}
const fullyVisible = box.y >= 0 && box.y + box.height <= viewport.height;
if (fullyVisible) {
const zoneMid = viewport.height * (cfg.scroll_target_zone[0] + cfg.scroll_target_zone[1]) / 2;
const needUp = box.y + box.height / 2 < zoneMid;
const { y, maxY } = await readScrollState(page);
if (needUp ? y <= 0 : y >= maxY) {
return { box, cursorX, cursorY, didScroll: false };
}
}
const scrollAreaX = Math.round(viewport.width * rand(0.3, 0.7));
const scrollAreaY = Math.round(viewport.height * rand(0.3, 0.7));
await humanMove(raw, cursorX, cursorY, scrollAreaX, scrollAreaY, cfg);View on GitHub (pinned to d6bad5de26)
Solutions
- Wait for the element to be actionable first: await page.locator(sel).waitFor({ state: 'visible' }) or use non-humanized scrollIntoViewIfNeeded to force reveal before the human action.
- Make the container visible (open the accordion/tab/dropdown) before acting on its children.
- If the element is in an iframe, switch page context to that frame — the snapshot only searches the main world's document.
- Tighten the selector so it matches the visible instance (e.g. add .first() or a visibility-scoped CSS class).
Example fix
// before
await humanClick(page, 'text=Accept Cookies'); // cookie banner not rendered yet
// after
await page.locator('text=Accept Cookies').waitFor({ state: 'visible' });
await humanClick(page, 'text=Accept Cookies'); Defensive patterns
Strategy: validation
Validate before calling
const loc = page.locator(selector).first();
await loc.waitFor({ state: 'visible' });
await humanClick(page, selector); // element now has a layout box Type guard
async function elementHasBox(page: Page, selector: string): Promise<boolean> {
try { return (await page.locator(selector).first().boundingBox()) !== null; }
catch { return false; }
} Try / catch
try {
await humanClick(page, selector);
} catch (e) {
if (e instanceof Error && e.message === 'Element not found while scrolling into view') {
await page.locator(selector).first().waitFor({ state: 'visible' });
await humanClick(page, selector);
} else throw e;
} Prevention
- Always waitFor({ state: 'visible' }) before humanized actions.
- Open containing accordions/tabs/dropdowns before targeting hidden children.
- Frame-switch first — the snapshot doesn't cross iframe boundaries.
When it happens
Trigger: Calling a humanized click/press or scrollToElement on a selector whose element is detached, display:none/hidden (zero, no layout box), inside a collapsed container, or when the snapshot resolves to nothing because the element hasn't rendered yet.
Common situations: Acting before an element is actually rendered (SPA hydration, lazy list virtualization, hidden tabs/accordions); element re-rendered between query and action; selectors matching only in a different frame; display:none until a CSS class toggles.
Related errors
- ElementNotAttachedError: {sourceSelector}
- ElementNotAttachedError: {targetSelector}
- Element ${selector} failed visible check: element is not vis
- Humanized selector ${selector} is not supported by the isola
- Humanized selector ${selector} is not supported by the isola
AI-assisted analysis of CloakHQ/CloakBrowser@d6bad5de26 (2026-08-28).
Data as JSON: /api/errors/a30c3d37010b7db6.
Report an issue: GitHub.