hcengineering/platform · error

CanvasStreamComposer: unable to get canvas context

Error message

CanvasStreamComposer: unable to get canvas context

What it means

createCanvasElement requests a 2D rendering context from a freshly created <canvas> with { alpha: false, desynchronized: true }. When canvas.getContext('2d') returns null — meaning the browser could not create a drawing surface — the recorder's CanvasStreamComposer throws this error because it cannot composite video frames without a 2D context.

Source

Thrown at plugins/recorder-resources/src/composer.ts:273

    case 'medium':
      return 0.15
    case 'large':
      return 0.2
    default:
      return 0.15
  }
}

function createCanvasElement (): { canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D } {
  const canvas = document.createElement('canvas')

  const ctx = canvas.getContext('2d', {
    alpha: false,
    desynchronized: true
  })

  if (ctx === null) {
    throw new Error('CanvasStreamComposer: unable to get canvas context')
  }

  ctx.imageSmoothingEnabled = true
  ctx.imageSmoothingQuality = 'high'

  return { canvas, ctx }
}

function createVideoElement (): HTMLVideoElement {
  const element = document.createElement('video')
  element.autoplay = true
  element.playsInline = true
  return element
}

function updateCameraPos (
  cameraSize: CameraSize,
  cameraPos: CameraPosition,

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Enable hardware acceleration in the browser (chrome://settings → 'Use hardware acceleration when available') and restart.
  2. Check browser/enterprise policy does not block canvas APIs (e.g. DisableWebGL/CanvasReadback policies).
  3. Reduce the requested canvas dimensions in the composer to stay within the browser's canvas size limits.
  4. Guard the call site: test document.createElement('canvas').getContext('2d') before constructing the composer and surface a graceful fallback (e.g. audio-only recording).

Example fix

// before
const { canvas, ctx } = createCanvasElement(w, h)

// after
function canvasSupported(): boolean {
  try {
    return document.createElement('canvas').getContext('2d') !== null
  } catch {
    return false
  }
}
if (!canvasSupported()) {
  // fall back to direct MediaRecorder on the stream, no compositing
  recorder = new Recorder(stream, options)
} else {
  composer = new CanvasStreamComposer(stream, w, h)
}
Defensive patterns

Strategy: fallback

Validate before calling

function canvas2dAvailable(): boolean {
  try {
    const c = document.createElement('canvas')
    return typeof c.getContext === 'function' && c.getContext('2d') !== null
  } catch {
    return false
  }
}
if (!canvas2dAvailable()) console.warn('Canvas 2D unavailable; recording will run without compositing')

Type guard

function has2dContext(canvas: HTMLCanvasElement): canvas is HTMLCanvasElement & { getContext: (t: '2d', o?: CanvasRenderingContext2DSettings) => CanvasRenderingContext2D } {
  return canvas.getContext('2d') !== null
}

Try / catch

let composer: CanvasStreamComposer | null = null
try {
  composer = new CanvasStreamComposer(stream, width, height)
} catch (err) {
  if (err instanceof Error && err.message.includes('unable to get canvas context')) {
    composer = null // degrade gracefully: record the raw stream instead
    recorder = new Recorder(stream, options)
  } else {
    throw err
  }
}

Prevention

When it happens

Trigger: Creating the recorder composer in an environment where getContext('2d') returns null: hardware acceleration disabled/unavailable, GPU process crash, browser with canvas support disabled by policy, memory exhaustion preventing backing-buffer allocation, or a non-DOM environment (SSR/headless without canvas).

Common situations: Corporate browsers with 'Disable canvas' / hardware-acceleration-off policies; Linux headless environments lacking GPU drivers; low-memory devices; Electron/webview builds with experimental canvas features disabled; huge requested canvas dimensions exceeding the browser's max canvas area.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/7789eafb34a7b824. Report an issue: GitHub.