{"record":{"id":"f3b01fd744490895","repo":"remotion-dev/remotion","slug":"failed-to-create-webgl-program-f3b01f","errorCode":null,"errorMessage":"Failed to create WebGL program","messagePattern":"Failed to create WebGL program","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/effects/src/speckle.ts","lineNumber":187,"sourceCode":"\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(`Speckle shader compile failed: ${log ?? '(no log)'}`);\n\t}\n\n\treturn shader;\n};\n\nconst linkProgram = (\n\tgl: WebGL2RenderingContext,\n\tvs: WebGLShader,\n\tfs: WebGLShader,\n): WebGLProgram => {\n\tconst program = gl.createProgram();\n\tif (!program) {\n\t\tthrow new Error('Failed to create WebGL program');\n\t}\n\n\tgl.attachShader(program, vs);\n\tgl.attachShader(program, fs);\n\tgl.linkProgram(program);\n\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\tconst log = gl.getProgramInfoLog(program);\n\t\tgl.deleteProgram(program);\n\t\tthrow new Error(`Speckle program link failed: ${log ?? '(no log)'}`);\n\t}\n\n\treturn program;\n};\n\nexport const speckle = createEffect<SpeckleParams, SpeckleState>({\n\ttype: 'dev.remotion.effects.speckle',\n\tlabel: 'speckle()',\n\tdocumentationLink: 'https://www.remotion.dev/docs/effects/speckle',","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/speckle.ts#L169-L205","documentation":"The speckle() effect's linkProgram() in packages/effects/src/speckle.ts calls gl.createProgram(); if it returns null the effect throws 'Failed to create WebGL program'. The shaders compiled, but the context cannot allocate a program object — typically due to context loss or a driver program-object limit being reached with many live WebGL2 effects.","triggerScenarios":"Context loss or program-resource exhaustion between shader compile and program creation inside the speckle setup; a driver imposing a low ceiling on live program objects when numerous WebGL2 effects are initialized concurrently.","commonSituations":"High render concurrency with many stacked WebGL2 effects; long-running renders leaking programs; headless/CI hosts without a real GPU; driver crash/reset during setup.","solutions":["Use ANGLE (--gl=angle / chromiumOptions.gl='angle' / Studio OpenGL=angle).","Lower concurrency and the count of simultaneous WebGL2 effects.","Ensure effect cleanup (gl.deleteProgram) runs so program handles are freed.","Render on a host with a supported GPU and current drivers."],"exampleFix":"// before\nawait renderMedia({ composition, serveUrl });\n// after\nawait renderMedia({ composition, serveUrl, chromiumOptions: { gl: 'angle' } });","handlingStrategy":"try-catch","validationCode":"function webgl2Available(): boolean {\n  try {\n    return !!document.createElement('canvas').getContext('webgl2');\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await renderMedia({ composition, codec: 'h264', chromiumOptions: { gl: 'angle' } });\n} catch (err) {\n  if (err instanceof Error && /Failed to create WebGL program/.test(err.message)) {\n    console.error('speckle() could not allocate a WebGL program (context lost/exhausted). Lower concurrency or switch GL backend.', err);\n    throw err;\n  }\n  throw err;\n}","preventionTips":["Render WebGL2 effects with ANGLE and modest concurrency.","Free effect resources before allocating new ones.","Watch for context-loss in long renders.","Use hosts with verified GPU/driver support."],"tags":["webgl","gpu","effects","speckle","rendering","context-loss"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}