BabylonJS/Babylon.js · critical
WebXRWebGLRenderTargetTextureProvider requires a WebGL-capab
Error message
WebXRWebGLRenderTargetTextureProvider requires a WebGL-capable engine.
What it means
_createInternalTexture wraps a raw WebGLTexture handed over by the XR compositor into a Babylon InternalTexture. It casts the engine to ThinEngine and reads its WebGL context (_gl). If the engine has no GL context (e.g. a WebGPU engine or an engine whose context was lost/disposed), the wrapping cannot proceed and this error is thrown.
Source
Thrown at packages/dev/core/src/XR/webXRWebGLRenderTargetTextureProvider.ts:19
import { type ThinEngine } from "../Engines/thinEngine";
import { WebGLHardwareTexture } from "../Engines/WebGL/webGLHardwareTexture";
import { type WebGLRenderTargetWrapper } from "../Engines/WebGL/webGLRenderTargetWrapper";
import { InternalTexture, InternalTextureSource } from "../Materials/Textures/internalTexture";
import { type RenderTargetTexture } from "../Materials/Textures/renderTargetTexture.pure";
import { type Nullable } from "../types";
import { WebXRLayerRenderTargetTextureProvider } from "./webXRRenderTargetTextureProvider";
import { type WebXRLayerType, type WebXRSupportedLayerType } from "./webXRLayerWrapper";
/**
* Provides render target textures for WebGL-backed XR layers. Owns all WebGL-specific
* framebuffer/texture wiring so the base provider can stay graphics-API-agnostic.
* @internal
*/
export abstract class WebXRWebGLRenderTargetTextureProvider<LayerTypeT extends WebXRSupportedLayerType = WebXRLayerType> extends WebXRLayerRenderTargetTextureProvider<LayerTypeT> {
private _createInternalTexture(textureSize: { width: number; height: number }, texture: WebGLTexture): InternalTexture {
const gl = (this._engine as ThinEngine)._gl;
if (!gl) {
throw new Error("WebXRWebGLRenderTargetTextureProvider requires a WebGL-capable engine.");
}
const internalTexture = new InternalTexture(this._engine, InternalTextureSource.Unknown, true);
internalTexture.width = textureSize.width;
internalTexture.height = textureSize.height;
internalTexture._hardwareTexture = new WebGLHardwareTexture(texture, gl);
internalTexture.isReady = true;
return internalTexture;
}
protected _createRenderTargetTexture(
width: number,
height: number,
framebuffer: Nullable<WebGLFramebuffer>,
colorTexture?: WebGLTexture,
depthStencilTexture?: WebGLTexture,
multiview?: boolean
): RenderTargetTexture {
if (!this._engine) {View on GitHub (pinned to 0592b347b8)
Solutions
- Create the app engine as a WebGL ThinEngine when using WebGL-based XR sessions (matching WebXRWebGLGraphicsBinding), not WebGPU.
- Use the WebGPU-specific XR path/binding (WebXRWebGPUGraphicsBinding and its texture provider) when the engine is WebGPU.
- Check `engine.isWebGL` / `(engine as ThinEngine)._gl` before setting up XR render target textures and choose the right provider.
- Recreate the WebGL context / engine if it was lost, then restart the XR session before requesting render target textures.
Example fix
// before const engine = new WebGPUEngine(canvas); // but using WebGL XR session layer const xrRTT = new WebXRWebGLRenderTargetTextureProvider(engine, xr); // throws // after const engine = new Engine(canvas, true); // WebGL engine for WebGL XR session const xrRTT = new WebXRWebGLRenderTargetTextureProvider(engine, xr);
Defensive patterns
Strategy: type-guard
Validate before calling
import { ThinEngine } from '@babylonjs/core/Engines/thinEngine';
const gl = (engine as ThinEngine)._gl;
if (!gl) {
throw new Error('Cannot set up WebGL XR render targets: no WebGL context');
} Type guard
function isWebGLEngine(engine: AbstractEngine): engine is ThinEngine {
return !engine.isWebGPU && !!(engine as ThinEngine)._gl;
} Try / catch
try {
const rtt = provider.getRenderTargetTextureForEye(eye);
} catch (e) {
if (e instanceof Error && e.message.includes('WebGL-capable engine')) {
console.error('Wrong engine type for WebGL XR session:', e.message);
return null;
}
throw e;
} Prevention
- Pair a WebGL engine with WebGL XR sessions and WebGPU engine with WebGPU XR paths
- Don't use NullEngine/disposed engines for XR render target providers
- Check engine.isWebGL / _gl before creating XR texture providers
- Handle context-loss events by rebuilding the XR pipeline, not reusing providers
When it happens
Trigger: Using a WebXR render target texture provider (WebXRWebGLRenderTargetTextureProvider._createRenderTargetTexture / internalTexture) with a WebGPU engine or an engine where _gl is null (context lost, engine disposed, NullEngine).
Common situations: Mixing WebGPU engine with a WebGL-only XR session (requestSession without gl context / wrong graphics binding type); running XR in a NullEngine test environment; engine context loss during an active XR session.
Related errors
- Invalid Space Warp framebuffer
- Expected a WebGL graphics binding for WebXR Depth Sensing.
- Atmosphere is not supported on WebGL ${engine.version}.
- Instanced arrays are required for MSDF text rendering.
- Unable to create multi sampled framebuffer
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/497eea1eb7fd805b.
Report an issue: GitHub.