remotion-dev/remotion · critical · Error
Failed to create WebGL texture
Error message
Failed to create WebGL texture
What it means
Thrown when `gl.createTexture()` returns null during lightTrail setup. The texture is the source sampling surface. Per-spec failure means context loss, OUT_OF_MEMORY, or texture-handle exhaustion — the most common real cause is leaking textures by not cleaning up effect state across many setups.
Source
Thrown at packages/effects/src/light-trail/light-trail-runtime.ts:88
};
const createProgram = (
gl: WebGL2RenderingContext,
vertexSource: string,
fragmentSource: string,
): WebGLProgram => {
const vs = compileShader(gl, gl.VERTEX_SHADER, vertexSource);
const fs = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
const program = linkProgram(gl, vs, fs);
gl.deleteShader(vs);
gl.deleteShader(fs);
return program;
};
const createRgbaTexture = (gl: WebGL2RenderingContext): WebGLTexture => {
const texture = gl.createTexture();
if (!texture) {
throw new Error('Failed to create WebGL texture');
}
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D, null);
return texture;
};
export const setupLightTrail = (target: HTMLCanvasElement): LightTrailState => {
const gl = target.getContext('webgl2', {
premultipliedAlpha: true,
alpha: true,
preserveDrawingBuffer: true,
});
if (!gl) {View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Always pair `setupLightTrail` with `cleanupLightTrail` (GL resources are not GC'd reliably).
- Cache the setup keyed by params (the effect already does this — make sure you are not bypassing it).
- On `webglcontextlost`, call cleanup and rebuild on restore.
- Cap concurrent active WebGL effects per worker.
Example fix
// before
useEffect(() => { setupLightTrail(canvas); }, []); // no cleanup
// after
useEffect(() => {
const state = setupLightTrail(canvas);
return () => cleanupLightTrail(state);
}, []); Defensive patterns
Strategy: fallback
Validate before calling
const texturePoolHealthy = (gl: WebGL2RenderingContext): boolean => {
const probe = gl.createTexture();
if (probe) { gl.deleteTexture(probe); return true; }
return false;
}; Try / catch
useEffect(() => {
let state: LightTrailState | null = null;
try { state = setupLightTrail(canvas); } catch (e) { state = null; }
return () => { if (state) cleanupLightTrail(state); };
}, []); Prevention
- Always call cleanupLightTrail in useEffect teardown.
- Cache setup by params; never re-allocate per frame.
- Recover on context loss/restore.
When it happens
Trigger: Repeatedly calling `setupLightTrail` without matching `cleanupLightTrail`; a frame loop that re-allocates state every render; context loss mid-setup.
Common situations: Forgetting cleanup in a hot-reload loop in Studio; long render sessions on Lambda that accumulate textures; many effects stacked and each setup leaks one texture.
Related errors
- Failed to create WebGL shader
- Light trail shader compile failed: ${log ?? '(no log)'}
- Failed to create WebGL program
- Light trail program link failed: ${log ?? '(no log)'}
- Failed to create WebGL vertex array
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/1f4997667b472c6e.
Report an issue: GitHub.