remotion-dev/remotion · critical · Error

Program link failed: ${log ?? '(no log)'}

Error message

Program link failed: ${log ?? '(no log)'}

What it means

Thrown by the barrel distortion effect's `linkProgram` helper when a vertex and fragment shader compile successfully but fail to link into a usable WebGL2 program. The GLSL sources are bundled constants (BARREL_DISTORTION_VS / BARREL_DISTORTION_FS), so a link failure indicates a shader-authoring bug or a driver that rejected the linked program (varying/in-out mismatch, unsupported feature). The error message appends the driver's info log when available.

Source

Thrown at packages/effects/src/barrel-distortion/barrel-distortion-runtime.ts:58

};

const linkProgram = (
	gl: WebGL2RenderingContext,
	vs: WebGLShader,
	fs: WebGLShader,
): WebGLProgram => {
	const program = gl.createProgram();
	if (!program) {
		throw new Error('Failed to create WebGL program');
	}

	gl.attachShader(program, vs);
	gl.attachShader(program, fs);
	gl.linkProgram(program);
	if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
		const log = gl.getProgramInfoLog(program);
		gl.deleteProgram(program);
		throw new Error(`Program link failed: ${log ?? '(no log)'}`);
	}

	return program;
};

const createProgram = (
	gl: WebGL2RenderingContext,
	vertexSource: string,
	fragmentSource: string,
): WebGLProgram => {
	const vs = compileShader(gl, gl.VERTEX_SHADER, vertexSource);
	const fs = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
	const program = linkProgram(gl, vs, fs);
	gl.deleteShader(vs);
	gl.deleteShader(fs);
	return program;
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Read the appended info log in the thrown message — it names the exact linker complaint (e.g. varying mismatch, undefined symbol).
  2. Update @remotion/effects to the latest patch; shader regressions are fixed upstream.
  3. Update your GPU drivers / browser; driver bugs sometimes surface as link failures.
  4. Reproduce on a second GPU/browser to isolate hardware-specific driver behavior.
  5. If running headless in CI, ensure Chrome uses a real GPU (or an accepted software WebGL2 path) rather than falling back to an unsupported context.

Example fix

// Not user-fixable at the call site — the shader sources are library constants.
// Action: report the info log from the error message to the Remotion issue tracker
// with your GPU vendor/renderer string:
debugger; // then capture gl.getParameter(gl.RENDERER) / gl.getParameter(gl.VERSION)
Defensive patterns

Strategy: fallback

Validate before calling

// Before setup, confirm the context can link programs at all.
const testProgram = gl.createProgram();
if (!testProgram) { /* skip barrel distortion, fall back */ }
gl.deleteProgram(testProgram);

Try / catch

try {
  const state = setupBarrelDistortion(canvas);
} catch (err) {
  if (String(err.message).startsWith('Program link failed')) {
    // fall back to a non-WebGL effect or skip
  } else { throw err; }
}

Prevention

When it happens

Trigger: Called inside `setupBarrelDistortion(target)` via `createProgram(gl, BARREL_DISTORTION_VS, BARREL_DISTORTION_FS)` -> `linkProgram`. Fires exactly when `gl.getProgramParameter(program, gl.LINK_STATUS)` returns a falsy value after `gl.linkProgram`.

Common situations: A new barrel-distortion shader revision ships with a vertex/fragment interface mismatch; running on a GPU driver with strict GLSL ES 3.00 enforcement; headless/CI software rasterizers (SwiftShader, llvmpipe) that reject constructs a discrete GPU accepts; corrupted build output that truncated the shader string.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/28c9ec1398b7460f. Report an issue: GitHub.