heygen-com/hyperframes · critical · ChromeBinaryUnavailableError

[chromium] Chrome binary unavailable (source=${source}): HYP

Error message

[chromium] Chrome binary unavailable (source=${source}): HYPERFRAMES_LAMBDA_CHROME_SOURCE=chrome-headless-shell requires HYPERFRAMES_LAMBDA_CHROME_PATH to be set to the absolute path of the bundled binary.

What it means

A `ChromeBinaryUnavailableError` thrown when the source is `chrome-headless-shell` (explicit fallback) but `HYPERFRAMES_LAMBDA_CHROME_PATH` is unset. The fallback resolver does not search PATH — it requires the operator to point at the bundled binary's absolute path because build-zip places it at a known location only when configured.

Source

Thrown at packages/aws-lambda/src/chromium.ts:113

    const mod = await loadSparticuzChromium();
    const path = await mod.executablePath();
    // Guard against the wedge described in ChromeBinaryUnavailableError.
    // sparticuz's contract is "return the path to a usable binary" — when
    // it returns null/undefined/"" we can't hand that to puppeteer-core
    // (which will throw an unrelated-looking assertion). Same when the
    // returned path doesn't exist (extraction failed but the function
    // call returned).
    if (!path || typeof path !== "string") {
      throw new ChromeBinaryUnavailableError(source, null, SPARTICUZ_WEDGE_HINT);
    }
    if (!existsSync(path)) {
      throw new ChromeBinaryUnavailableError(source, path, SPARTICUZ_WEDGE_HINT);
    }
    return path;
  }
  const explicit = process.env.HYPERFRAMES_LAMBDA_CHROME_PATH;
  if (!explicit) {
    throw new ChromeBinaryUnavailableError(
      source,
      null,
      "HYPERFRAMES_LAMBDA_CHROME_SOURCE=chrome-headless-shell requires " +
        "HYPERFRAMES_LAMBDA_CHROME_PATH to be set to the absolute path of the bundled binary.",
    );
  }
  if (!existsSync(explicit)) {
    throw new ChromeBinaryUnavailableError(
      source,
      explicit,
      `HYPERFRAMES_LAMBDA_CHROME_PATH=${JSON.stringify(explicit)} does not exist on disk.`,
    );
  }
  return explicit;
}

/**
 * Resolve the Chromium launch args for the selected source. For

View on GitHub (pinned to c2996c8626)

Solutions

  1. Set HYPERFRAMES_LAMBDA_CHROME_PATH to the absolute path of the bundled chrome-headless-shell binary inside the Lambda zip.
  2. Or switch back to the sparticuz source: `HYPERFRAMES_LAMBDA_CHROME_SOURCE=sparticuz`.
  3. Verify build-zip.ts actually bundles the binary at the configured path.
  4. For SAM-local, pass the env var through template.yaml / event overrides.

Example fix

# before
HYPERFRAMES_LAMBDA_CHROME_SOURCE=chrome-headless-shell
# after
HYPERFRAMES_LAMBDA_CHROME_SOURCE=chrome-headless-shell
HYPERFRAMES_LAMBDA_CHROME_PATH=/var/task/bin/chrome-headless-shell
Defensive patterns

Strategy: validation

Validate before calling

function assertChromeConfigured(): void {
  const source = process.env.HYPERFRAMES_LAMBDA_CHROME_SOURCE;
  if (source === "chrome-headless-shell" && !process.env.HYPERFRAMES_LAMBDA_CHROME_PATH) {
    throw new Error("HYPERFRAMES_LAMBDA_CHROME_PATH required for chrome-headless-shell source");
  }
}
// call at cold start

Prevention

When it happens

Trigger: `resolveChromeExecutablePath()` with `HYPERFRAMES_LAMBDA_CHROME_SOURCE=chrome-headless-shell` and `process.env.HYPERFRAMES_LAMBDA_CHROME_PATH` falsy — i.e. the deploy set the source discriminator without wiring the path, or a SAM-local run forgot the override.

Common situations: Misconfigured deploy that set `HYPERFRAMES_LAMBDA_CHROME_SOURCE` to the fallback without bundling the binary or setting its path; SAM-local RIE smoke run missing the env override; build-zip.ts change that stopped emitting the path env var.

Related errors


AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12). Data as JSON: /api/errors/bdea255b5217cf1d. Report an issue: GitHub.