{"record":{"id":"428511773491ce85","repo":"remotion-dev/remotion","slug":"program-link-failed-log-no-log-428511","errorCode":null,"errorMessage":"Program link failed: ${log ?? '(no log)'}","messagePattern":"Program link failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/effects/src/wave/wave-runtime.ts","lineNumber":59,"sourceCode":"};\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(`Program link failed: ${log ?? '(no log)'}`);\n\t}\n\n\treturn program;\n};\n\nconst createProgram = (\n\tgl: WebGL2RenderingContext,\n\tvertexSource: string,\n\tfragmentSource: string,\n): WebGLProgram => {\n\tconst vs = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n\tconst fs = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n\tconst program = linkProgram(gl, vs, fs);\n\tgl.deleteShader(vs);\n\tgl.deleteShader(fs);\n\treturn program;\n};\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/wave/wave-runtime.ts#L41-L77","documentation":"Thrown by the wave effect's linkProgram() when gl.linkProgram() succeeds in calling but gl.getProgramParameter(program, gl.LINK_STATUS) returns false. This means the vertex and fragment shaders compiled individually but could not be linked into a single executable program — typically due to mismatched varying declarations, missing attribute bindings, or a GPU driver bug. The error message includes the info log from the GL driver for diagnostics.","triggerScenarios":"Called transitively from setupWave() at packages/effects/src/wave/wave-runtime.ts:118 via createProgram(gl, WAVE_VS, WAVE_FS). The shaders WAVE_VS/WAVE_FS are static library constants, so this fires when the GL driver rejects the linked program — not from user params. Most common when the WebGL2 context is in a degraded state or the GPU driver has a bug with the specific GLSL ES 3.00 construct used.","commonSituations":"Headless Chromium with SwiftShader software rendering rejecting a GLSL construct; outdated GPU drivers on Windows; a transient WebGL context loss mid-setup; running in a CI environment with a software rasterizer that has partial WebGL2 support; virtual machines with passthrough GPU drivers.","solutions":["Update your GPU drivers to the latest version — link failures with valid shaders are almost always driver bugs.","If rendering server-side (Remotion Lambda / headless Chrome), ensure the Chrome binary bundled with @remotion/renderer matches the platform's GPU/SwiftShader capabilities and is up to date.","Check the browser console for a preceding 'webglcontextlost' event; if the context was lost, the canvas must be recreated before retrying setupWave.","Try disabling hardware acceleration in the render environment (or conversely enabling it if currently on software) to switch between the GPU driver and SwiftShader.","Report the issue to Remotion with the full info log from the error message and your GPU/driver details (chrome://gpu)."],"exampleFix":"// Cannot be fixed from user code — the shaders are internal constants.\n// Workaround: fall back to a non-WebGL effect or retry on a fresh canvas.\n// before\nimport {wave} from '@remotion/effects';\nconst state = setupWave(canvas); // may throw link failure\n\n// after: wrap setup so a context loss or driver bug doesn't crash the render\ntry {\n  const state = setupWave(canvas);\n} catch (e) {\n  console.error('Wave effect unavailable on this GPU:', (e as Error).message);\n  // fall back to a CSS/native effect or skip the wave overlay\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Wrap effect application so a link failure (driver bug) degrades gracefully.\n// The error originates inside setupWave, so catch at the point of use.\nimport {wave} from '@remotion/effects';\n\ntry {\n  // If using the effect via the framework, wrap the component/frame logic\n  state = setupWave(canvas);\n} catch (e) {\n  if ((e as Error).message.startsWith('Program link failed')) {\n    // GPU/driver issue — log and skip the effect\n    console.warn('Wave effect unavailable:', (e as Error).message);\n  } else {\n    throw e; // re-throw unrelated errors\n  }\n}","preventionTips":["Keep GPU drivers and the rendering browser up to date.","For server-side rendering, use the Chrome build bundled with @remotion/renderer.","Test WebGL2 effects in your target render environment before deploying."],"tags":["webgl","gpu","shader","wave-effect","driver"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}