remotion-dev/remotion · error · Error
Failed to create WebGL shader
Error message
Failed to create WebGL shader
What it means
Thrown by the duotone effect's internal compileShader() when gl.createShader(type) returns null. The WebGL2 context was already acquired successfully (createWebGL2ContextError would have thrown earlier otherwise), so a null shader object means the driver refused to allocate one. Per the WebGL spec, createShader returns null only when the context is lost or the implementation cannot create another resource.
Source
Thrown at packages/effects/src/duotone.ts:138
return;
}
vec3 rgb = texColor.rgb / alpha;
float luminance = dot(rgb, vec3(0.299, 0.587, 0.114));
vec3 duotoneColor = luminance < uThreshold ? uDarkColor : uLightColor;
fragColor = vec4(duotoneColor * alpha, alpha);
}
`;
const compileShader = (
gl: WebGL2RenderingContext,
type: number,
source: string,
): WebGLShader => {
const shader = gl.createShader(type);
if (!shader) {
throw new Error('Failed to create WebGL shader');
}
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
const log = gl.getShaderInfoLog(shader);
gl.deleteShader(shader);
throw new Error(`Duotone shader compile failed: ${log ?? '(no log)'}`);
}
return shader;
};
const linkProgram = (
gl: WebGL2RenderingContext,
vs: WebGLShader,
fs: WebGLShader,
): WebGLProgram => {View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Render with a software/ANGLE WebGL backend, e.g. `npx remotion render <comp> --output out.mp4 --gl=swiftshader` (also try --gl=angle, --gl=swangle).
- Enable hardware acceleration in the browser used for Studio preview, or run preview on a machine with a working GPU.
- Lower render concurrency (--concurrency) so each frame's WebGL contexts are created and torn down without exhausting GPU resources.
- Update the Chromium build Remotion drives (newer builds carry GPU-process fixes); on Lambda, use a current Chrome layer.
Defensive patterns
Strategy: try-catch
Try / catch
// Resource-allocation failures are GPU-state dependent and cannot be predicted,
// so catch the render promise and retry on a different GL backend.
async function safeRender(opts) {
try {
return await renderMedia(opts);
} catch (err) {
if (/WebGL/.test(String(err?.message ?? ''))) {
return await renderMedia({...opts, gl: 'swiftshader'});
}
throw err;
}
} Prevention
- Pin a reliable GL backend for your environment: pass `gl: 'swiftshader'` (or 'angle') to renderMedia/renderMediaOnLambda.
- Cap render concurrency so per-frame WebGL contexts are not created faster than the GPU can serve them.
- Run Studio preview with hardware acceleration enabled, or on a machine with a working GPU.
- Keep the Chromium build Remotion drives current; GPU-process fixes land regularly.
When it happens
Trigger: Calling duotone() in a composition that is being rendered or previewed on a Chrome instance whose GPU process is unavailable, has crashed, or has exhausted its WebGL object budget. The failure occurs inside setupDuotone() during the first frame that wires up the duotone program.
Common situations: Headless/CI Chrome with no GPU access, hardware acceleration disabled in the local browser, too many simultaneous WebGL contexts (many concurrent render workers or several GPU effects on one frame), a GPU driver reset mid-render.
Related errors
- Failed to create WebGL program
- Failed to create WebGL texture
- Failed to create WebGL vertex array
- Failed to create WebGL buffer
- Failed to create WebGL shader
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/6691e9b03417f3e6.
Report an issue: GitHub.