{"record":{"id":"d01a6a566ca52ec2","repo":"remotion-dev/remotion","slug":"failed-to-create-webgl-shader-d01a6a","errorCode":null,"errorMessage":"Failed to create WebGL shader","messagePattern":"Failed to create WebGL shader","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/effects/src/liquid-contours.ts","lineNumber":287,"sourceCode":"\tfloat detailedField = fbm(p + warp * mix(0.35, 1.8, uComplexity));\n\tfloat detailMix = smoothstep(0.0, 1.0, uComplexity);\n\tfloat field = mix(roundedField, detailedField, detailMix);\n\tfloat levels = max(max(uResolution.x, uResolution.y) / max(uSpacing, 0.001), 1.0);\n\tfloat wave = sin((field * levels + uPhase) * 6.28318530718);\n\tfloat edgeWidth = fwidth(wave) * mix(0.15, 1.4, uSmoothness);\n\tfloat selector = smoothstep(-edgeWidth, edgeWidth, wave);\n\tvec4 color = mix(uFirstColor, uSecondColor, selector);\n\tfragColor = vec4(color.rgb * color.a, color.a);\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) throw new Error('Failed to create WebGL shader');\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`Liquid contours shader compile failed: ${log ?? '(no log)'}`,\n\t\t);\n\t}\n\n\treturn shader;\n};\n\nconst createProgram = (gl: WebGL2RenderingContext): WebGLProgram => {\n\tconst vs = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER);\n\tconst fs = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);\n\tconst program = gl.createProgram();\n\tif (!program) throw new Error('Failed to create WebGL program');","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/liquid-contours.ts#L269-L305","documentation":"A plain Error thrown inside compileShader in the Liquid contours effect when gl.createShader(type) returns null. Identical contract to the Lines effect: WebGL2 may return null under resource exhaustion or context loss, and the effect aborts instead of dereferencing null.","triggerScenarios":"The WebGL2 context exists (passed the earlier createWebGL2ContextError check for 'liquid contours effect') but cannot allocate a shader object. GPU memory exhaustion, too many live shaders, or a lost context.","commonSituations":"Many concurrent Remotion renders; a page that leaked GL objects; headless software GL with a small budget; transient context-loss during a long render.","solutions":["Reduce concurrent browser contexts / render parallelism.","Confirm the host WebGL2 stack is healthy with a smoke test.","Handle webglcontextlost / webglcontextrestored and re-instantiate the effect."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"function webgl2Ready(): boolean {\n  const c = document.createElement('canvas');\n  const gl = c.getContext('webgl2');\n  const ok = !!gl && !!gl.createShader(gl.VERTEX_SHADER);\n  return ok;\n}","typeGuard":null,"tryCatchPattern":"try {\n  liquidContours(...);\n} catch (err) {\n  if (err instanceof Error && /WebGL shader/.test(err.message)) {\n    // fall back or surface 'GPU unavailable'\n  } else throw err;\n}","preventionTips":["Smoke-test gl.createShader on the target browser before rendering.","Cap concurrent render contexts to keep GPU shader objects available.","Use a known-good GL backend for headless Chrome."],"tags":["webgl2","liquid-contours-effect","gpu","resource-exhaustion","headless"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}