CloakHQ/CloakBrowser · error · Error

CloakBrowser Pro: license key is invalid or expired (plan=${

Error message

CloakBrowser Pro: license key is invalid or expired (plan=${info.plan}). Check CLOAKBROWSER_LICENSE_KEY, or unset it to use the free binary.

What it means

RuntimeError('Element lost after scrolling into view') is raised at the end of human_scroll_into_view when get_box() returns None after the wheel-scroll burst and settle delay. The element existed when scrolling started but was detached or hidden by the time scrolling finished — typically the page re-rendered, lazy-loaded content shifted layout, or navigation occurred.

Source

Thrown at js/src/download.ts:131

          proVersion,
          info.plan,
          releaseChannel,
        );
      } catch (e) {
        // Authenticity could not be confirmed — surface verbatim.
        if (e instanceof BinaryVerificationError) throw e;
        // Transient failure with no cached Pro binary to use — surface a clear
        // error rather than silently downloading the free binary.
        throw new Error(
          `Pro binary unavailable: ${e}. Your license is valid but the Pro ` +
            `binary could not be downloaded right now. Retry in a moment. To use ` +
            `the free binary instead, unset CLOAKBROWSER_LICENSE_KEY.`,
          { cause: e }
        );
      }
    } else if (info) {
      // Key supplied but rejected — abort, never downgrade to free.
      throw new Error(
        `CloakBrowser Pro: license key is invalid or expired (plan=${info.plan}). ` +
          `Check CLOAKBROWSER_LICENSE_KEY, or unset it to use the free binary.`,
      );
    } else {
      // Key supplied but unvalidatable (server down, no cache) — abort.
      throw new Error(
        "CloakBrowser Pro: license could not be validated (server unreachable " +
          "and no cached validation). Retry in a moment, or unset " +
          "CLOAKBROWSER_LICENSE_KEY to use the free binary.",
      );
    }
  }

  // Fail fast if no binary available for this platform
  checkPlatformAvailable();

  if (requestedVersion) {
    const binaryPath = getBinaryPath(requestedVersion);

View on GitHub (pinned to d6bad5de26)

Solutions

  1. Re-query the element by selector after catching this error and retry the scroll once — node identity often changes but the selector still matches.
  2. Wait for layout to stabilize before scrolling (networkidle or a data-loaded marker) so lazy content does not shift mid-scroll.
  3. Increase cfg.scroll_settle_delay if re-render consistently lands after the settle window.
  4. For virtualized lists, scroll by fixed offsets instead of targeting recycled nodes.

Example fix

// before
box, cx, cy, scrolled = human_scroll_into_view(page, sel, get_box, cfg)

// after
try:
    box, cx, cy, scrolled = human_scroll_into_view(page, sel, get_box, cfg)
except RuntimeError as e:
    if 'lost after scrolling' in str(e):
        page.wait_for_selector(sel, state='visible', timeout=3000)
        box, cx, cy, scrolled = human_scroll_into_view(page, sel, get_box, cfg)
    else:
        raise
Defensive patterns

Strategy: retry

Validate before calling

# no reliable pre-check; ensure layout is stable
page.wait_for_selector(sel, state='visible')

Try / catch

try:
    human_scroll_into_view(page, sel, get_box, cfg)
except RuntimeError as e:
    if 'lost after scrolling' not in str(e): raise
    page.wait_for_selector(sel, state='visible', timeout=3000)
    human_scroll_into_view(page, sel, get_box, cfg)

Prevention

When it happens

Trigger: Scrolling an element inside a virtualized list or React/Vue tree that re-renders nodes on scroll; an anchor click triggered by the scroll; lazy-load placeholders replacing the target node; navigation during the settle delay (cfg.scroll_settle_delay).

Common situations: Infinite-scroll feeds and virtualized tables that recycle DOM nodes; SPAs with skeleton-to-content swaps; ads/interstitials mounting on scroll; slow networks where the element unmounts mid-scroll.

Related errors


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