CloakHQ/CloakBrowser · error · StealthEvaluationError
Isolated-world DOM evaluation failed for "<viewport>"
Error message
Isolated-world DOM evaluation failed for "<viewport>"
What it means
When page.viewportSize() is unavailable, humanScrollIntoView evaluates VIEWPORT_JS inside the isolated world to get {width,height}. If that evaluate call throws (context destroyed, navigation, world teardown), the error is normalized to StealthEvaluationError('<viewport>'). The viewport probe itself failed, not the element lookup.
Source
Thrown at js/src/human/scroll.ts:92
}
}
export async function humanScrollIntoView<T extends ElementBounds>(
page: Page,
raw: RawMouse,
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 };View on GitHub (pinned to d6bad5de26)
Solutions
- Set an explicit context viewport (newContext({ viewport: {...} })) so the world-based viewport probe is skipped entirely.
- Await a stable state (waitForLoadState / element visible) before the humanized action.
- Retry the action once the page settles if it occasionally races navigation.
- Ensure the page isn't being closed/navigated by other code while the action runs.
Example fix
// before
const context = await browser.newContext(); // headful, no viewport
await humanClick(page, 'text=Buy');
// after
const context = await browser.newContext({ viewport: { width: 1366, height: 768 } });
await humanClick(page, 'text=Buy'); Defensive patterns
Strategy: retry
Validate before calling
if (!page.viewportSize()) await page.waitForLoadState('domcontentloaded');
await scrollToElement(page, raw, selector);
// strongest prevention: newContext({ viewport: { width: 1280, height: 720 } }) Type guard
null
Try / catch
try {
await humanClick(page, selector);
} catch (e) {
if (e instanceof StealthEvaluationError && e.message.includes('<viewport>')) {
await page.waitForLoadState('load');
await humanClick(page, selector);
} else throw e;
} Prevention
- Set an explicit viewport on every context to bypass the world probe.
- Avoid actions that coincide with redirects/reloads.
- Keep one owner for page interactions; don't close/navigate concurrently.
When it happens
Trigger: page.viewportSize() === null AND world.evaluate(VIEWPORT_JS) rejects — typically a headful page that navigates/reloads at the moment of the humanized action, or an isolated world whose execution context was invalidated.
Common situations: Headful runs on SPAs that navigate during clicks; humanized clicks fired immediately after page.goto before load completes; concurrent actions tearing down the world; flaky CDP connectivity in grid/docker setups.
Related errors
- Isolated-world DOM evaluation failed for ${selector}
- Invalid browser version pin. Use a full numeric Chromium ver
- Unsupported platform: ${platform} ${arch}. Supported: ${supp
- Isolated-world DOM evaluation failed for ${selector}
- Humanized DOM read requires an active isolated world
AI-assisted analysis of CloakHQ/CloakBrowser@d6bad5de26 (2026-08-28).
Data as JSON: /api/errors/d6809ed05fdc32fe.
Report an issue: GitHub.