CloakHQ/CloakBrowser · error · ElementNotVisibleError

Element ${selector} failed visible check: element is not vis

Error message

Element ${selector} failed visible check: element is not visible

What it means

The element was found and evaluated, but with the 'visible' check requested the probe reported data.visible === false (zero size, display:none, visibility:hidden, or hidden ancestor).

Source

Thrown at js/src/human/actionability.ts:119

// ---------------------------------------------------------------------------
// Pre-scroll actionability
// ---------------------------------------------------------------------------

async function stealthActionable(
  pageOrFrame: Page | Frame,
  selector: string,
  checks: ReadonlySet<CheckName>,
): Promise<void> {
  const world = getWorld(pageOrFrame);
  if (!world) throw new StealthWorldUnavailableError();

  const { status, data } = await evalParsed(world, buildActionableJs(selector));
  if (status === UNSUPPORTED) throw new UnsupportedHumanizeSelectorError(selector);
  if (status === EVALUATION_FAILED) throw new StealthEvaluationError(selector);
  if (status === NOT_FOUND) throw new ElementNotAttachedError(selector);
  if (status !== OK || !data) throw new StealthEvaluationError(selector);
  if (checks.has('visible') && !data.visible) throw new ElementNotVisibleError(selector);
  if (checks.has('enabled') && !data.enabled) throw new ElementNotEnabledError(selector);
  if (checks.has('editable') && !data.editable) throw new ElementNotEditableError(selector);
}

async function readBox(
  pageOrFrame: Page | Frame,
  selector: string,
): Promise<{ x: number; y: number; width: number; height: number } | null> {
  const world = getWorld(pageOrFrame);
  if (!world) throw new StealthWorldUnavailableError();

  const { status, data } = await evalParsed(world, buildBoxJs(selector));
  if (status === OK && data?.box) return data.box;
  if (status === NOT_FOUND) return null;
  if (status === UNSUPPORTED) throw new UnsupportedHumanizeSelectorError(selector);
  throw new StealthEvaluationError(selector);
}

View on GitHub (pinned to d6bad5de26)

Solutions

  1. Trigger the UI state that reveals the element first (open the dropdown, switch tab, scroll into view)
  2. Await visibility before acting: expect(locator).toBeVisible() or waitForSelector with state:'visible'
  3. Increase the action timeout so animation/transition periods are covered
  4. If acting on a hidden element is intentional, drop 'visible' from the checks set or use native Playwright

Example fix

// before
await humanClick(page, '[data-testid="menu-item-2"]');
// after
await humanClick(page, '[data-testid="menu"]'); // open menu
await page.waitForSelector('[data-testid="menu-item-2"]', { state: 'visible' });
await humanClick(page, '[data-testid="menu-item-2"]');
Defensive patterns

Strategy: validation

Validate before calling

await page.locator(sel).waitFor({ state: 'visible', timeout: 5000 });

Type guard

function isElementNotVisibleError(e: unknown): e is ElementNotVisibleError {
  return e instanceof Error && /failed visible check/.test(e.message);
}

Try / catch

try { await humanClick(page, sel); } catch (e) { if (isElementNotVisibleError(e)) { await openMenuFirst(); await humanClick(page, sel); } else throw e; }

Prevention

When it happens

Trigger: Calling ensureActionable with 'visible' in checks (default for click/hover/type actions) on an element that is hidden — e.g. a dropdown menu not yet opened, a modal overlay state, or an element mid-animation.

Common situations: Clicking menu items before opening the menu, tabs whose inactive panes are display:none, CSS animations mid-transition, off-screen carousels, or elements hidden by responsive breakpoints in emulated viewports.

Related errors


AI-assisted analysis of CloakHQ/CloakBrowser@d6bad5de26 (2026-08-28). Data as JSON: /api/errors/1776b4c6fd600724. Report an issue: GitHub.