heygen-com/hyperframes · error · Error
beginFrame screenshot returned
Error message
beginFrame screenshot returned ${bytes.length} bytes after ${BEGINFRAME_SCREENSHOT_PROBE_ATTEMPTS} attempts with signature ${bytes.length >= 4 ? bytes.subarray(0, 4).toString("hex") : "<empty>"} What it means
Thrown after the beginFrame screenshot probe exhausts all BEGINFRAME_SCREENSHOT_PROBE_ATTEMPTS (10) retries without obtaining a valid PNG. Each attempt calls screenshot and checks the first 4 bytes for the PNG magic number (89 50 4E 47). The error includes byte count and hex signature for diagnostics, revealing whether Chrome returned empty data, JPEG, or garbage.
Solutions
- Check the hex signature in the error: '<empty>' means no data at all (beginFrame not functional); a JPEG signature means format negotiation failed.
- Use a standard Chrome headless shell build: run hyperframes browser ensure.
- If on a custom Chrome, verify it supports HeadlessExperimental.beginFrame with PNG screenshots.
- The probe gracefully reports supported: false on failure — ensure downstream code falls back to non-beginFrame capture.
Defensive patterns
Strategy: fallback
Try / catch
let beginFrameSupported = true;
try {
const result = await probeBeginFrameSupport(browser);
beginFrameSupported = result.supported;
} catch (err) {
if (err instanceof Error && err.message.includes('beginFrame screenshot returned')) {
beginFrameSupported = false;
} else {
throw err;
}
}
// use beginFrame capture only if beginFrameSupported === true Prevention
- Use hyperframes browser ensure to get a standard Chrome headless shell that supports beginFrame PNG screenshots.
- Inspect the hex signature in the error message to diagnose the specific Chrome output format issue.
- Treat probe failure as 'unsupported' and implement a non-beginFrame fallback capture path.
When it happens
Trigger: The probe loop calls client.send('Page.captureScreenshot', { format: 'png' }) up to 10 times with 10ms delays. Every result fails the PNG signature check (bytes[0]===0x89 && bytes[1]===0x50 && bytes[2]===0x4e && bytes[3]===0x47). After the last attempt, the isPng flag is still false and the error fires.
Common situations: The Chrome headless shell doesn't support beginFrame screenshot capture properly (older or stripped build). The page hasn't rendered any content yet (empty/blank screenshots). A GPU/compositing issue produces corrupted frame data. The headless shell is a non-standard build that returns JPEG or raw data instead of PNG.
Related errors
- beginFrame probe timeout before
- Audio FX failed for track
- BeginFrame probe timeout before
- Audio FX produced no samples for track
- audio FX runtime failed to load
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/6cc1b5f5a39f4144.
Report an issue: GitHub.
Appendix: source
Thrown at packages/engine/src/services/browserManager.ts:388
`screenshot beginFrame attempt ${attempts}`,
);
const screenshot = response.screenshotData ?? "";
bytes = screenshot ? Buffer.from(screenshot, "base64") : Buffer.alloc(0);
isPng =
bytes.length >= 8 &&
bytes[0] === 0x89 &&
bytes[1] === 0x50 &&
bytes[2] === 0x4e &&
bytes[3] === 0x47;
if (isPng) break;
await awaitBeforeDeadline(
new Promise((resolveDelay) => setTimeout(resolveDelay, 10)),
deadline,
`screenshot retry delay ${attempts}`,
);
}
if (!isPng) {
throw new Error(
`beginFrame screenshot returned ${bytes.length} bytes after ` +
`${BEGINFRAME_SCREENSHOT_PROBE_ATTEMPTS} attempts with signature ` +
`${bytes.length >= 4 ? bytes.subarray(0, 4).toString("hex") : "<empty>"}`,
);
}
await awaitBeforeDeadline(client.detach(), deadline, "CDP detach").catch(() => {});
result = {
supported: true,
detail:
`enable + warm-up + ${bytes.length}-byte PNG beginFrame succeeded ` +
`after ${attempts} screenshot attempt(s)`,
durationMs: Date.now() - started,
};
} catch (error) {
result = {
supported: false,
detail: error instanceof Error ? error.message : String(error),
durationMs: Date.now() - started,View on GitHub (pinned to c2996c8626)