CloakHQ/CloakBrowser · error · Error

Pinned download completed but binary not found at expected p

Error message

Pinned download completed but binary not found at expected path: ${binaryPath}. This may indicate a packaging issue. Please report at https://github.com/CloakHQ/cloakbrowser/issues

What it means

UnsupportedHumanizeSelectorError(selector) is raised in _get_element_box_async when the isolated-world geometry script reports UNSUPPORTED for the given selector. The humanizer only supports a subset of selector engines (typically CSS) inside the isolated world, so XPath, text=, and other Playwright-specific engines are rejected.

Source

Thrown at js/src/download.ts:161

  }

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

  if (requestedVersion) {
    const binaryPath = getBinaryPath(requestedVersion);
    if (fs.existsSync(binaryPath) && isExecutable(binaryPath)) {
      showWelcome();
      return binaryPath;
    }

    console.log(
      `[cloakbrowser] Stealth Chromium ${requestedVersion} not found. Downloading for ${getPlatformTag()}...`
    );
    await downloadAndExtract(requestedVersion);

    if (!fs.existsSync(binaryPath) || !isExecutable(binaryPath)) {
      throw new Error(
        `Pinned download completed but binary not found at expected path: ${binaryPath}. ` +
          `This may indicate a packaging issue. Please report at ` +
          `https://github.com/CloakHQ/cloakbrowser/issues`
      );
    }
    showWelcome();
    return binaryPath;
  }

  // Check for auto-updated version first, then fall back to hardcoded
  const effective = getEffectiveVersion();
  const binaryPath = getBinaryPath(effective);

  if (fs.existsSync(binaryPath) && isExecutable(binaryPath)) {
    showWelcome();
    maybeTriggerUpdateCheck();
    return binaryPath;
  }

View on GitHub (pinned to d6bad5de26)

Solutions

  1. Convert the selector to pure CSS: replace XPath/text selectors with CSS equivalents (e.g. `a[href='/login']`, `[data-testid='submit']`).
  2. If you only have a Playwright Locator, resolve it to a CSS path or use its bounding element's stable attribute selector.
  3. Check the library's supported selector list in the humanize module docs before passing values.

Example fix

// before
box = await _get_element_box_async(page, "text=Sign in")

// after
box = await _get_element_box_async(page, "button[data-testid='sign-in']")
Defensive patterns

Strategy: validation

Validate before calling

import re
assert not re.search(r"(^//|text=|>> |:has-text|nth=)", sel), 'use pure CSS selectors for humanize'

Type guard

def is_supported_selector(sel: str) -> bool:
    import re
    return re.fullmatch(r"[a-zA-Z0-9_\-\[\]\.\='#:\"\s\*,>\(\)]+", sel) is not None and not sel.startswith('//')

Try / catch

try:
    box = await _get_element_box_async(page, sel)
except UnsupportedHumanizeSelectorError:
    box = await _get_element_box_async(page, css_equivalent(sel))

Prevention

When it happens

Trigger: Passing selectors like `//div[@id='x']`, `text=Sign in`, or `div >> nth=0` to async humanized get/scroll helpers — build_box_js cannot compile them into the isolated-world query, returning UNSUPPORTED.

Common situations: Copy-pasting selectors from Playwright traces or devtools; recorded scripts using get_by_text equivalents; refactoring from page.locator pipelines into humanized helpers without converting selector syntax.

Related errors


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