heygen-com/hyperframes · error · Error
Render failed for variant "${variant.label}" (${variant.disp
Error message
Render failed for variant "${variant.label}" (${variant.displayPath}): ${normalizeErrorMessage(err)} What it means
The outer catch in renderCompareVariant(): it wraps EVERY failure inside the per-variant render pipeline — bundleToSingleHtml, serveStaticProjectHtml, openSettledCompositionPage (Puppeteer/Chrome), seekCompositionTimeline, and page.screenshot — into one Error tagged with the variant label, displayPath, and the normalized inner message. It is a catch-all, so the inner cause is what matters.
Source
Thrown at packages/cli/src/commands/compare.ts:299
renderReadyTimedOut,
} = await openSettledCompositionPage(html, server.url, {
renderReadyTimeoutMs: opts.timeoutMs,
renderReadyWarningSuffix: `comparison variant "${variant.label}" may be inaccurate`,
});
try {
if (opts.atSeconds > 0) {
await seekCompositionTimeline(page, opts.atSeconds);
}
await page.screenshot({ path: opts.framePath, type: "png" });
return { framePath: opts.framePath, renderReadyTimedOut };
} finally {
await chromeBrowser.close();
}
} finally {
await server.close();
}
} catch (err) {
throw new Error(
`Render failed for variant "${variant.label}" (${variant.displayPath}): ${normalizeErrorMessage(err)}`,
);
}
}
async function renderCompareSheet(parsed: ParsedCompareArgs): Promise<CompareSuccessPayload> {
const capResult = capCompareVariants(parsed.variants);
const variants = capResult.variants;
const prepared = prepareCompareVariantProjects(variants);
const frameDir = mkdtempSync(join(tmpdir(), "hf-compare-frames-"));
const framePaths: string[] = [];
try {
let renderReadyTimedOut = false;
for (let i = 0; i < prepared.length; i++) {
const variant = prepared[i]!;
const framePath = join(frameDir, `variant-${String(i + 1).padStart(2, "0")}.png`);
const rendered = await renderCompareVariant(variant, {View on GitHub (pinned to c2996c8626)
Solutions
- Read the normalized inner message in the thrown error — it names the actual root cause
- Run `hyperframes lint` and `hyperframes check` on the failing variant composition
- Verify Chrome is installed and the --out directory is writable
- Lower --at to a value within the composition duration
Defensive patterns
Strategy: try-catch
Try / catch
try {
await renderCompareVariant(variant, opts);
} catch (err) {
// The wrapper already includes label + displayPath + inner cause.
// Inspect err.message for the normalized root cause before deciding.
console.error(`compare variant ${variant.label} failed:`, (err as Error).message);
throw err;
} Prevention
- Run `hyperframes lint` and `hyperframes check` on each variant composition before comparing
- Ensure Chrome/Puppeteer is installed and the --out directory is writable
- Keep --at within each composition's timeline duration
When it happens
Trigger: Composition HTML is malformed so bundling fails; Chrome/Puppeteer is missing or crashes; the static project server cannot bind its port; seekCompositionTimeline fails (no GSAP timeline / no seek adapter registered on window.__timelines); the screenshot path is unwritable; --at is beyond the timeline duration.
Common situations: Chrome not installed in CI; a variant composition missing data-* attributes or shipping broken JS; --out pointing at a read-only or non-existent directory; a very short timeline combined with a large --at.
Related errors
- [build-zip] chrome-headless-shell cache missing at ${baseDir
- [getRenderProgress] executionArn is required
- [renderToLambda] bucketName is required
- [renderToLambda] stateMachineArn is required
- [renderToLambda] either siteHandle or projectDir must be sup
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/b6a0927609074b5e.
Report an issue: GitHub.