heygen-com/hyperframes · error · Error

drawElement canvas not initialized

Error message

drawElement canvas not initialized

What it means

Thrown during the drawElement capture evaluate when document.getElementById('__hf_de_canvas') returns null or document.querySelector('[data-composition-id]') returns null. The canvas with id '__hf_de_canvas' is injected by injectDrawElementCanvas(); if that injection was never called, failed, or was reverted, the capture step cannot find its target.

Source

Thrown at packages/engine/src/services/drawElementService.ts:334

  syncToPaintEvent = true,
): Promise<Buffer> {
  const dataUrl = await page.evaluate(
    ({
      w,
      h,
      fmt,
      q,
      sync,
    }: {
      w: number;
      h: number;
      fmt: "jpeg" | "png";
      q: number;
      sync: boolean;
    }) => {
      const canvas = document.getElementById("__hf_de_canvas") as HTMLCanvasElement | null;
      const root = document.querySelector("[data-composition-id]") as HTMLElement | null;
      if (!canvas || !root) throw new Error("drawElement canvas not initialized");
      const ctx = canvas.getContext("2d");
      if (!ctx) throw new Error("drawElement: 2d context unavailable");
      // Accelerated canvases (webgl/webgl2/webgpu) never repaint — their paint
      // record stays frozen at the first frame (see instrumentAcceleratedCanvases).
      // Hide them NOW, before this frame's paint, so the stale record stops
      // painting; drawAndEncode composites their live content via drawImage
      // underneath the drawElementImage output instead. Hiding must happen
      // before the paint wait (sync mode) so the awaited paint reflects it.
      type AccelWindow = Window & {
        __hf_accel_canvases?: HTMLCanvasElement[];
        __hf_canvas_2d?: HTMLCanvasElement[];
        __hf3d?: { update: () => void };
        __hfDeInvalidate?: () => boolean;
        __HF_ROOT_PROPS__?: boolean;
        __HF_ROOT_BASE_OPACITY__?: number;
      };
      const aw = window as AccelWindow;
      // True when this frame's paint was requested via canvas.requestPaint()

View on GitHub (pinned to c2996c8626)

Solutions

  1. Ensure injectDrawElementCanvas(page, w, h) is called and awaited before any capture call.
  2. If the page may navigate, re-inject after each navigation: call injectDrawElementCanvas again.
  3. Check for composition scripts that manipulate document.body innerHTML and might destroy the canvas.
  4. Add a guard: if document.getElementById('__hf_de_canvas') is null, re-run injection before capture.
Defensive patterns

Strategy: validation

Validate before calling

const canvasReady = await page.evaluate(() =>
  document.getElementById('__hf_de_canvas') !== null
);
if (!canvasReady) {
  await injectDrawElementCanvas(page, w, h);
}

Try / catch

try {
  await captureDrawElement(page, captureOpts);
} catch (err) {
  if (err instanceof Error && err.message.includes('canvas not initialized')) {
    await injectDrawElementCanvas(page, w, h);
    await captureDrawElement(page, captureOpts);
  }
  throw err;
}

Prevention

When it happens

Trigger: The capture function (drawAndEncode or its evaluate callback) runs page.evaluate to get the canvas element by id and the root by attribute. If injectDrawElementCanvas was skipped, threw before creating the canvas, or the page reloaded after injection, both lookups fail.

Common situations: injectDrawElementCanvas was not called before the first frame capture. The page navigated or reloaded between injection and capture. A composition script removed or replaced the canvas element. The canvas id was changed by a conflicting script.

Related errors


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