{"record":{"id":"8e9497c0e06ef835","repo":"remotion-dev/remotion","slug":"duotone-shader-compile-failed-log-no-log","errorCode":null,"errorMessage":"Duotone shader compile failed: ${log ?? '(no log)'}","messagePattern":"Duotone shader compile failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/effects/src/duotone.ts","lineNumber":146,"sourceCode":"}\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(`Duotone 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);","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/duotone.ts#L128-L164","documentation":"Thrown by duotone's compileShader() when gl.getShaderParameter(shader, gl.COMPILE_STATUS) is false. The driver's info log is embedded in the message. Because DUOTONE_VS / DUOTONE_FS are hardcoded #version 300 es GLSL constants inside the library (the caller never supplies shader source), a compile failure is never a user-input problem: it indicates the WebGL2 driver cannot translate or accept the library's GLSL ES 3.00 shader.","triggerScenarios":"Rendering or previewing duotone() on a GPU/driver that rejects the bundled vertex or fragment shader. The shader source is fixed; only the driver varies.","commonSituations":"Outdated or buggy GPU drivers, an ANGLE/SwiftShader regression, a virtualized or headless environment with incomplete WebGL2 shader translation, or a Chromium update that changed how the shader is compiled.","solutions":["Switch the render GL backend and re-render: `npx remotion render <comp> --gl=swiftshader` (or --gl=angle / --gl=swangle) to bypass the failing driver path.","Update the system GPU driver and/or the Chromium build Remotion uses.","If rendering on Lambda, confirm the function uses a supported Chrome layer version.","If the failure reproduces identically across swiftshader, angle, and swangle, file a Remotion bug with the full shader info log from the message."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// You cannot 'fix' a driver rejecting a fixed library shader; fall back to a\n// software/ANGLE backend that translates GLSL differently.\nasync function renderWithFallback(opts) {\n  try {\n    return await renderMedia(opts);\n  } catch (err) {\n    const msg = String(err?.message ?? '');\n    if (/shader compile failed/i.test(msg)) {\n      return await renderMedia({...opts, gl: 'swiftshader'});\n    }\n    throw err;\n  }\n}","preventionTips":["Choose a known-good GL backend for the target platform (swiftshader is the safest headless default).","Update GPU drivers and the Chromium build before debugging shader failures.","On Lambda, use a current Chrome layer so the bundled shader translator is up to date.","Keep the embedded info log when reporting; it identifies the exact GLSL line the driver rejected."],"tags":["webgl","glsl","shader","gpu","effects","rendering"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}