heygen-com/hyperframes · critical · ChromeBinaryUnavailableError
[chromium] Chrome binary unavailable (source=${source}): @sp
Error message
[chromium] Chrome binary unavailable (source=${source}): @sparticuz/chromium.executablePath() returned a falsy value or a path that doesn't exist on disk. This typically happens after a chunk hits `Sandbox.Timedout` mid-extraction and leaves /tmp in a wedged state — subsequent invocations land on the same warm instance and never re-extract. Recycle the function (e.g. `aws lambda update-function-configuration ... --environment ...` with a bumped marker var, or redeploy via `hyperframes lambda deploy --skip-build`) to force fresh execution environments. Tracking: investigate the upstream wedge so this auto-recovers. What it means
A `ChromeBinaryUnavailableError` thrown when `@sparticuz/chromium`'s `executablePath()` resolves to a non-string (null/undefined/empty). The resolver refuses to forward a falsy value to puppeteer-core because puppeteer would surface an unrelated-looking assertion instead. The hint points at a known `Sandbox.Timedout` mid-extraction wedge that leaves `/tmp` dirty on warm Lambda instances.
Source
Thrown at packages/aws-lambda/src/chromium.ts:104
*
* For `"chrome-headless-shell"`: read the path from
* `HYPERFRAMES_LAMBDA_CHROME_PATH`. Throws if absent or non-existent so a
* misconfigured deploy fails loudly at boot rather than at first frame.
*/
// fallow-ignore-next-line complexity
export async function resolveChromeExecutablePath(): Promise<string> {
const source = resolveChromeSource();
if (source === "sparticuz") {
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,View on GitHub (pinned to c2996c8626)
Solutions
- Recycle the Lambda execution environment: `aws lambda update-function-configuration --function-name <fn> --environment Variables=<existing>,HF_RECYCLE_MARKER=$(date +%s)` to force fresh containers.
- Redeploy with `hyperframes lambda deploy --skip-build` to get new instances.
- Bump the Lambda timeout / memory so extraction completes before `Sandbox.Timedout`.
- Pin or upgrade @sparticuz/chromium to a known-good version for your Lambda node runtime.
- Investigate the upstream wedge so warm instances auto-recover (tracking note in the hint).
Example fix
# before: warm instance wedged
aws lambda invoke --function-name my-fn out.json
# after: recycle to force re-extraction
aws lambda update-function-configuration --function-name my-fn --environment "Variables={HF_RECYCLE_MARKER=$(date +%s)}" Defensive patterns
Strategy: retry
Type guard
function isUsableChromiumPath(path: unknown): path is string {
return typeof path === "string" && path.length > 0;
} Try / catch
import { ChromeBinaryUnavailableError } from "@hyperframes/aws-lambda";
try {
const p = await resolveChromeExecutablePath();
} catch (err) {
if (err instanceof ChromeBinaryUnavailableError && err.source === "sparticuz") {
// recycle the environment via update-function-configuration / redeploy, then retry
}
throw err;
} Prevention
- Run the BeginFrame probe in CI on the same Lambda image to catch sparticuz regressions before deploy.
- Pin @sparticuz/chromium to a known-good version and update deliberately.
- Add a startup health check that calls executablePath() on cold start and recycles on failure.
- Alert on ChromeBinaryUnavailableError in CloudWatch and auto-trigger a recycle.
When it happens
Trigger: `resolveChromeExecutablePath()` with `HYPERFRAMES_LAMBDA_CHROME_SOURCE=sparticuz` where `mod.executablePath()` returns null/undefined/"" — typically because a prior extraction timed out and the warm container never re-extracts.
Common situations: Lambda warm instance wedged after a `Sandbox.Timedout` mid-extraction; corrupted/incomplete `/tmp/chromium` extraction from a previous invocation; @sparticuz/chromium version regression that changed `executablePath()` semantics.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- [chromium] Chrome binary unavailable (source=${source}): HYP
- [chromium] Chrome binary unavailable (source=${source}): HYP
- BeginFrame probe timeout before ${label}
- [handler] unknown Action: ${JSON.stringify((_exhaustive as {
- [handler] event has no recognised Action; unwrapped ${MAX_EN
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/4c742fdec15ad83e.
Report an issue: GitHub.