{"record":{"id":"a50c027f4cad46e1","repo":"heygen-com/hyperframes","slug":"screenshot-returned-no-data","errorCode":null,"errorMessage":"screenshot returned no data","messagePattern":"screenshot returned no data","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/cli/src/commands/motionShot.ts","lineNumber":634,"sourceCode":"  )) as OnionElement[];\n\n  const windowStr = frame.hasWindow ? `  ·  t ${times[0]}–${times[times.length - 1]}s` : \"\";\n  const label = `${cameraLabel(camera)}  ·  ${frame.layout === \"strip\" ? \"filmstrip\" : frame.fit ? \"zoom-fit\" : \"1:1\"}  ·  ${times.length} frames${windowStr}`;\n  const svg = buildOnionSvg(elements, {\n    layout: frame.layout,\n    fit: frame.fit,\n    width: size.width,\n    height: size.height,\n    label,\n  });\n\n  await page.evaluate((markup: string) => {\n    document.body.insertAdjacentHTML(\"beforeend\", markup);\n  }, svg);\n  await new Promise((r) => setTimeout(r, 60));\n\n  const buf = await page.screenshot({ type: \"png\" });\n  if (!buf) throw new Error(\"screenshot returned no data\");\n  writeFileSync(outPath, buf as Uint8Array);\n  return outPath;\n}\n\n/** Render `projectDir`'s index headless, sample each element's motion as a 3D\n *  onion-skin, screenshot to `outPath` (PNG). Returns the saved path. */\nexport async function captureMotionPathShot(\n  projectDir: string,\n  requestsIn: ShotRequest[],\n  outPath: string,\n  opts: ShotOptions = {},\n): Promise<string> {\n  ensureShotOutputDir(outPath);\n  let requests = requestsIn;\n  const samples = Math.max(1, Math.min(60, opts.samples ?? 9));\n  const layout = opts.layout ?? \"path\";\n  const fit = opts.fit ?? true;\n  const camera = parseAngle(opts.angle);","sourceCodeStart":616,"sourceCodeEnd":652,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/motionShot.ts#L616-L652","documentation":"Thrown by captureMarkerOnionSkin when page.screenshot({ type: 'png' }) returns a falsy buffer. Puppeteer normally returns a Uint8Array; a null/empty result indicates the headless browser failed to capture — typically a GPU process crash, a page navigation/close during capture, or a DevTools protocol error.","triggerScenarios":"Headless Chrome GPU process crash mid-screenshot. The page navigating or closing between the SVG insert and the screenshot call. A CDP protocol disconnection. Extreme viewport sizes that fail allocation.","commonSituations":"Unstable headless Chrome in CI (especially under --use-gl=swiftshader). Compositions with very large canvas sizes. Browser binaries mismatched with the puppeteer-core version. OOM conditions.","solutions":["Retry the shot once — transient headless crashes often succeed on retry","Pin a known-good Chrome/Chromium executable version compatible with puppeteer-core","Reduce the composition viewport size if it is very large","Check GPU mode resolution (resolveCaptureBrowserGpuMode) and force swiftshader or hardware as appropriate for the environment","Ensure no code navigates or closes the page during capture"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-flight: confirm the page is alive and the viewport is reasonable before capture\nconst alive = await page.evaluate(() => !!(document && document.body));\nif (!alive) throw new Error('Page unavailable before screenshot');\nif (size.width * size.height > 16_000_000) throw new Error('Viewport too large for stable screenshot');","typeGuard":null,"tryCatchPattern":"async function screenshotWithRetry(page: Page, attempts = 2): Promise<Uint8Array> {\n  for (let i = 0; i < attempts; i++) {\n    const buf = await page.screenshot({ type: 'png' });\n    if (buf) return buf as Uint8Array;\n  }\n  throw new Error('screenshot returned no data after retries');\n}","preventionTips":["Pin a Chrome/Chromium version known compatible with the bundled puppeteer-core","Avoid extremely large viewports that can fail allocation in headless mode","Ensure no navigation/close happens between SVG insertion and screenshot"],"tags":["motion-shot","screenshot","puppeteer","headless-chrome","rendering"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}