BabylonJS/Babylon.js · error
Unable to get 2d context
Error message
Unable to get 2d context
What it means
When copying a video frame into a texture, the engine creates an offscreen canvas and requests a '2d' rendering context from it. If canvas.getContext('2d') returns null, this error is thrown. getContext returns null only when a context of a different type was already requested on that canvas or the canvas is unusable.
Source
Thrown at packages/dev/core/src/Engines/Extensions/engine.videoTexture.pure.ts:52
this._gl.getError();
this._gl.texImage2D(this._gl.TEXTURE_2D, 0, internalFormat, glformat, this._gl.UNSIGNED_BYTE, video);
if (this._gl.getError() !== 0) {
this._videoTextureSupported = false;
} else {
this._videoTextureSupported = true;
}
}
// Copy video through the current working canvas if video texture is not supported
if (!this._videoTextureSupported) {
if (!texture._workingCanvas) {
texture._workingCanvas = this.createCanvas(texture.width, texture.height);
const context = texture._workingCanvas.getContext("2d");
if (!context) {
throw new Error("Unable to get 2d context");
}
texture._workingContext = context;
texture._workingCanvas.width = texture.width;
texture._workingCanvas.height = texture.height;
}
texture._workingContext!.clearRect(0, 0, texture.width, texture.height);
texture._workingContext!.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, texture.width, texture.height);
this._gl.texImage2D(this._gl.TEXTURE_2D, 0, internalFormat, glformat, this._gl.UNSIGNED_BYTE, texture._workingCanvas as TexImageSource);
} else {
this._gl.texImage2D(this._gl.TEXTURE_2D, 0, internalFormat, glformat, this._gl.UNSIGNED_BYTE, video);
}
if (texture.generateMipMaps) {
this._gl.generateMipmap(this._gl.TEXTURE_2D);
}
View on GitHub (pinned to 0592b347b8)
Solutions
- Ensure the working canvas used for video texture copies is dedicated and never previously requested as a 'webgl' (or other) context — create a fresh canvas per texture
- If reusing a canvas, check canvas.getContext('2d') yourself before handing it to the engine and use a separate canvas if null
- Update to a recent Babylon.js version; older videoTexture fallback paths had canvas-reuse bugs
- Rule out browser settings/extensions that block canvas contexts (privacy modes, canvas blockers)
Example fix
// before
const shared = document.createElement('canvas');
shared.getContext('webgl');
engine.createVideoTexture(url, { canvas: shared });
// after
const dedicated = document.createElement('canvas'); // no prior context request
engine.createVideoTexture(url, null, { ...options }); Defensive patterns
Strategy: validation
Validate before calling
function hasUsable2DCanvas(engine: any): boolean {
const probe = engine.createCanvas(1, 1);
const ctx = probe.getContext('2d');
return !!ctx;
} Type guard
function is2DContext(ctx: CanvasRenderingContext2D | null): ctx is CanvasRenderingContext2D {
return ctx !== null;
} Prevention
- Never request a 'webgl' context on a canvas you intend to hand to video texture copying
- Use a dedicated, freshly created canvas per video texture
- Test video texture creation in all target browsers early (policies differ)
- Keep Babylon.js updated — video texture canvas fallbacks have been fixed over time
When it happens
Trigger: Calling video texture creation (e.g. engine.createVideoTexture, or _createVideoTexture fallback path used by WebXR layers) where texture._workingCanvas already had a non-2d context (e.g. 'webgl') obtained earlier, so getContext('2d') returns null.
Common situations: Reusing the same HTMLCanvasElement across both a WebGL texture and a 2d drawing surface; WebXR passthrough/layers fallback path creating a canvas whose context type conflicts; browser policies or extensions blocking canvas 2d contexts.
Related errors
- Unable to create webGL texture
- The provided canvas is null or undefined.
- Atmosphere is not supported on WebGL ${engine.version}.
- Failed to get client rect for rendering canvas
- Instanced arrays are required for MSDF text rendering.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/3f6a0bed66a2c686.
Report an issue: GitHub.