{"record":{"id":"ed4f65be3780b1c2","repo":"remotion-dev/remotion","slug":"failed-to-create-webgl-shader-ed4f65","errorCode":null,"errorMessage":"Failed to create WebGL shader","messagePattern":"Failed to create WebGL shader","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/effects/src/progressive-pixelate-runtime.ts","lineNumber":127,"sourceCode":"\tfloat lowerBlockSize = exp2(floor(level));\n\tfloat upperBlockSize = lowerBlockSize * 2.0;\n\tfloat levelProgress = fract(level);\n\tfragColor = mix(\n\t\tsamplePixelated(lowerBlockSize),\n\t\tsamplePixelated(upperBlockSize),\n\t\tlevelProgress\n\t);\n}\n`;\n\nconst compileShader = (\n\tgl: WebGL2RenderingContext,\n\ttype: number,\n\tsource: string,\n): WebGLShader => {\n\tconst shader = gl.createShader(type);\n\tif (!shader) {\n\t\tthrow new Error('Failed to create WebGL shader');\n\t}\n\n\tgl.shaderSource(shader, source);\n\tgl.compileShader(shader);\n\tif (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n\t\tconst log = gl.getShaderInfoLog(shader);\n\t\tgl.deleteShader(shader);\n\t\tthrow new Error(\n\t\t\t`Progressive pixelate shader compile failed: ${log ?? '(no log)'}`,\n\t\t);\n\t}\n\n\treturn shader;\n};\n\nconst linkProgram = (\n\tgl: WebGL2RenderingContext,\n\tvs: WebGLShader,","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/progressive-pixelate-runtime.ts#L109-L145","documentation":"Thrown by compileShader in progressive-pixelate-runtime.ts when gl.createShader() returns null during setupProgressivePixelate. Same root cause as the pixelate equivalent (GL cannot allocate a shader object — context lost or exhausted), but for the progressive-pixelate effect which uses a more complex GLSL program.","triggerScenarios":"setupProgressivePixelate() calls compileShader for VERTEX_SHADER or FRAGMENT_SHADER; gl.createShader(type) returns null before any GLSL source is loaded.","commonSituations":"Headless Chrome/SwiftShader without working shader allocation; context lost before setup; many effects compiled in one tab; virtualized GPU with a low shader cap.","solutions":["Probe shader allocation in the target environment before mounting progressive pixelate.","Use the published Remotion Lambda Chrome layer with SwiftShader enabled.","Reduce concurrent WebGL2 effects.","Handle 'webglcontextlost' and remount on 'webglcontextrestored'.","Update the GPU driver on reproducible machines."],"exampleFix":"// before\nimport {setupProgressivePixelate} from '@remotion/effects/progressive-pixelate-runtime';\nsetupProgressivePixelate(canvas);\n\n// after — probe first\nfunction canCompileShader(gl: WebGL2RenderingContext): boolean {\n  const s = gl.createShader(gl.VERTEX_SHADER);\n  if (s) gl.deleteShader(s);\n  return s !== null;\n}","handlingStrategy":"try-catch","validationCode":"function glCanCreateShader(gl: WebGL2RenderingContext): boolean {\n  if (gl.isContextLost()) return false;\n  const s = gl.createShader(gl.VERTEX_SHADER);\n  if (s) gl.deleteShader(s);\n  return s !== null;\n}","typeGuard":null,"tryCatchPattern":"try {\n  setupProgressivePixelate(canvas);\n} catch (err) {\n  if (/Failed to create WebGL shader/.test((err as Error).message)) {\n    // report WebGL2 unavailable; fall back\n  }\n  throw err;\n}","preventionTips":["Feature-detect shader allocation in headless/CI before rendering.","On Lambda use the published Chrome for Testing layer.","Handle context loss and remount on restore.","Limit concurrent WebGL2 effects."],"tags":["webgl","gpu","progressive-pixelate","shader","environment","headless"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}