{"record":{"id":"0d7bf76c32ec15e6","repo":"remotion-dev/remotion","slug":"failed-to-create-webgl-shader-0d7bf7","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/noise-displacement.ts","lineNumber":405,"sourceCode":"\n\t\t\tfloat weight = passWeight * DISC_W[b];\n\t\t\tcolor += sampleSource(samplePixel + DISC[b] * blurRadius) * weight;\n\t\t\ttotalWeight += weight;\n\t\t}\n\t}\n\n\tfragColor = color / totalWeight;\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`Noise displacement 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":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/noise-displacement.ts#L387-L423","documentation":"While setting up the noiseDisplacement effect's WebGL2 pipeline, compileShader called gl.createShader() which returned null. The WebGL2 context exists (an earlier check would have thrown createWebGL2ContextError) but cannot allocate shader objects — typically due to context loss, GPU resource exhaustion, or an inadequate rendering environment.","triggerScenarios":"During setupNoiseDisplacement, gl.createShader(type) returns null for either the vertex (NOISE_DISPLACEMENT_VS) or fragment (NOISE_DISPLACEMENT_FS) shader. This occurs after the context is acquired but before shader source is uploaded.","commonSituations":"CI/headless rendering without proper GPU flags; too many concurrent WebGL contexts; context loss from browser crashes; VMs/Docker without GPU passthrough; corrupted GPU drivers.","solutions":["Ensure the render environment supports WebGL2 — for headless Chrome pass --enable-webgl and appropriate --use-gl flags.","Reduce the number of concurrent WebGL-based effects.","Update GPU drivers or use SwiftShader software rendering.","Handle WebGL context loss and retry the render."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Check WebGL2 shader allocation capability before using the effect\nconst testCanvas = document.createElement('canvas');\nconst testGl = testCanvas.getContext('webgl2');\nif (testGl) {\n  const testShader = testGl.createShader(testGl.VERTEX_SHADER);\n  if (!testShader) {\n    console.warn('WebGL2 shader allocation failed — noiseDisplacement may not work');\n  }\n  testGl.deleteShader(testShader);\n}","typeGuard":null,"tryCatchPattern":"// Wrap effect usage in try-catch with a non-WebGL fallback\ntry {\n  // apply noiseDisplacement effect\n} catch (e) {\n  if (e instanceof Error && e.message.includes('WebGL shader')) {\n    console.warn('WebGL unavailable, skipping noiseDisplacement effect');\n    // fall back to rendering without the effect\n  } else {\n    throw e;\n  }\n}","preventionTips":["Ensure the render environment (especially CI/headless) has working WebGL2 with proper Chrome GPU flags.","Monitor WebGL context loss and handle it gracefully.","Limit the number of concurrent WebGL effects to avoid resource exhaustion."],"tags":["webgl","gpu","environment","noise-displacement","rendering"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}