transloadit/uppy · error · Error
Failed to get canvas context
Error message
Failed to get canvas context
What it means
captureScreenshot creates an offscreen canvas and throws when canvas.getContext('2d') returns null. Browsers return null for a 2d context when the canvas has zero or invalid dimensions — here video.videoWidth/videoHeight are 0 because the video element has no loaded metadata yet.
Source
Thrown at packages/@uppy/screen-capture/src/ScreenCapture.tsx:566
}
const video = document.createElement('video')
video.srcObject = stream
await new Promise((resolve) => {
video.onloadedmetadata = () => {
video.play()
resolve(null)
}
})
const canvas = document.createElement('canvas')
canvas.width = video.videoWidth
canvas.height = video.videoHeight
const ctx = canvas.getContext('2d')
if (!ctx) {
throw new Error('Failed to get canvas context')
}
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
// Validate and set fallback for preferred image mime type
let mimeType = this.opts.preferredImageMimeType
if (!mimeType || !SUPPORTED_IMAGE_TYPES.includes(mimeType)) {
this.uppy.log(
`Unsupported image type "${mimeType}", falling back to image/png`,
'warning',
)
mimeType = 'image/png'
}
const quality = 1
return new Promise((resolve, reject) => {
canvas.toBlob(View on GitHub (pinned to 5d4dedd02a)
Solutions
- Retry the screenshot after a short delay or after the stream's video track is delivering frames (requestVideoFrameCallback)
- Ensure the video element is muted and play() is awaited before capture
- Verify the stream's track is live (track.readyState === 'live') before capturing
Example fix
// before
video.srcObject = stream
// immediately draw -> canvas.width = 0 -> ctx null
// after
video.srcObject = stream
await new Promise((r) => { video.onloadedmetadata = r })
await video.play()
if (video.videoWidth === 0) throw new Error('No frames yet') Defensive patterns
Strategy: retry
Validate before calling
if (videoRef.videoWidth === 0 || videoRef.videoHeight === 0) {
// wait for frames before allowing screenshot
} Type guard
const hasVideoFrames = (v: HTMLVideoElement): boolean => v.readyState >= 2 && v.videoWidth > 0
Try / catch
try { await plugin.captureScreenshot() } catch (e) { if (e.message === 'Failed to get canvas context') setTimeout(() => plugin.captureScreenshot(), 500) } Prevention
- Await video metadata/first frame before capture
- Verify stream tracks are live before screenshotting
- Retry once after a short delay — often a warm-up race
When it happens
Trigger: Calling captureScreenshot before the temporary video element fired loadedmetadata/loadeddata, so videoWidth/videoHeight are 0 and the context cannot be created (spec: getContext returns null if width/height are 0 in some engines, or the context is otherwise unavailable).
Common situations: Slow source warm-up, a stream with an ended/inactive video track, GPU/canvas context exhaustion, or browser quirks when the video was never played/muted to kick off decoding.
Related errors
- could not extract blob, probably an old browser
- All files were canceled after assembly was created
- No video stream available
- Screen capture is not supported
- Failed to get screen capture stream
AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28).
Data as JSON: /api/errors/2e0b6a4043d24351.
Report an issue: GitHub.