AvaloniaUI/Avalonia · error · Error
HTMLCanvasElement.getContext returned null.
Error message
HTMLCanvasElement.getContext returned null.
What it means
Thrown by the WebGlRenderTarget constructor when canvas.getContext('webgl'/'webgl2') returns null. The request uses failIfMajorPerformanceCaveat:true, so a context backed only by a software rasterizer is deliberately rejected, and a genuine null means the browser declined to create a WebGL context.
Source
Thrown at src/Browser/Avalonia.Browser/webapp/modules/avalonia/rendering/webGlRenderTarget.ts:56
depth: true,
stencil: true,
antialias: false,
premultipliedAlpha: true,
preserveDrawingBuffer: false,
// only supported on older browsers, which is perfect as we want to fallback to 2d there.
failIfMajorPerformanceCaveat: true,
// attrs used by Emscripten:
majorVersion: mode === BrowserRenderingMode.WebGL1 ? 1 : 2,
minorVersion: 0,
enableExtensionsByDefault: 1,
explicitSwapControl: 0
};
const context = (mode === BrowserRenderingMode.WebGL1
? canvas.getContext("webgl", attrs)
: canvas.getContext("webgl2", attrs)) as WebGLRenderingContext;
if (!context) {
throw new Error("HTMLCanvasElement.getContext returned null.");
}
const handle = WebGlRenderTarget._gl.registerContext(context, attrs);
(context as any).gl_handle = handle;
super(canvas, "webgl");
this.contextHandle = handle;
this.fboId = context.getParameter(context.FRAMEBUFFER_BINDING)?.id ?? 0;
this.stencil = context.getParameter(context.STENCIL_BITS);
this.sample = context.getParameter(context.SAMPLES);
this.depth = context.getParameter(context.DEPTH_BITS);
this.attrs = attrs;
}
public static getCurrentContext(): number {
return WebGlRenderTarget._gl?.currentContext?.handle ?? 0;
}
View on GitHub (pinned to 11c5427268)
Solutions
- List WebGL1 before WebGL2 in preferredModes so browsers without WebGL2 can fall back.
- Keep Software2D as the last preferred mode so createRenderTarget can recover.
- Ensure the canvas given to WebGL has not already acquired a 2D context and was not transferred offscreen.
- For headless tests, launch the browser with software WebGL flags or supply a WebGL polyfill.
Example fix
// before preferredModes = [BrowserRenderingMode.WebGL2, BrowserRenderingMode.WebGL1] // -> WebGL2 null on an older device throws and aborts // after preferredModes = [BrowserRenderingMode.WebGL2, BrowserRenderingMode.WebGL1, BrowserRenderingMode.Software2D]
Defensive patterns
Strategy: fallback
Validate before calling
function supportsMode(mode: BrowserRenderingMode, canvas: HTMLCanvasElement | OffscreenCanvas): boolean {
const t = mode === BrowserRenderingMode.WebGL1 ? 'webgl' : 'webgl2';
return canvas.getContext(t) != null; // note: probe only; do not consume in production
} Type guard
function hasWebGL2(canvas: HTMLCanvasElement | OffscreenCanvas): boolean {
return canvas.getContext('webgl2') != null;
} Try / catch
try { return new WebGlRenderTarget(canvas, mode); }
catch (e) {
if (e instanceof Error && /getContext/.test(e.message)) { /* try next preferred mode */ }
throw e;
} Prevention
- Order preferredModes [WebGL2, WebGL1, Software2D].
- Do not reuse a canvas that already has a 2D context for WebGL.
- In headless CI, enable software-WebGL or rely on Software2D.
When it happens
Trigger: Requesting a 'webgl2' context on a browser/device that only supports WebGL1; a canvas already bound to a 2D context; the device uses a software WebGL implementation (blocked by failIfMajorPerformanceCaveat); WebGL disabled in the browser; the canvas was consumed by transferControlToOffscreen on the main thread.
Common situations: Older/mobile browsers without WebGL2; headless CI browsers with no GPU; user disabled hardware acceleration; failIfMajorPerformanceCaveat rejecting a SwiftShader fallback; reusing a canvas that already got a 2D context for software rendering.
Related errors
- Module.GL object wasn't initialized, WebGL can't be used.
- Unable to access .NET memory
- Unable to access emscripten PThread api
- Unable get pthread with id ${pthreadId}
- Unable get Worker for pthread ${pthreadId}
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/ec14e0fbbe61d3a0.
Report an issue: GitHub.