remotion-dev/remotion · critical · Error

Blur framebuffer incomplete: 0x${status.toString(16)}

Error message

Blur framebuffer incomplete: 0x${status.toString(16)}

What it means

Thrown by `setupBlur` after the intermediate framebuffer is assembled and `gl.checkFramebufferStatus(gl.FRAMEBUFFER)` returns a value other than FRAMEBUFFER_COMPLETE. The hex status code is embedded (e.g. 0x8cd6 = FRAMEBUFFER_INCOMPLETE_ATTACHMENT). This is a format/config incompatibility between the intermediate texture and the framebuffer attachment, not a resource exhaustion error.

Source

Thrown at packages/effects/src/blur/blur-runtime.ts:187

		0,
		gl.RGBA,
		gl.UNSIGNED_BYTE,
		null,
	);
	gl.bindTexture(gl.TEXTURE_2D, null);

	gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
	gl.framebufferTexture2D(
		gl.FRAMEBUFFER,
		gl.COLOR_ATTACHMENT0,
		gl.TEXTURE_2D,
		textureIntermediate,
		0,
	);
	const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
	gl.bindFramebuffer(gl.FRAMEBUFFER, null);
	if (status !== gl.FRAMEBUFFER_COMPLETE) {
		throw new Error(`Blur framebuffer incomplete: 0x${status.toString(16)}`);
	}

	return {
		gl,
		programHorizontal,
		programVertical,
		vao,
		vbo,
		textureSource,
		textureIntermediate,
		framebuffer,
		horizontal: getBlurUniforms(gl, programHorizontal),
		vertical: getBlurUniforms(gl, programVertical),
	};
};

export const cleanupBlur = (state: BlurState): void => {
	const {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Decode the hex status in the message (0x8cd6 incomplete attachment, 0x8cdb unsupported, 0x8cd9 dimensions mismatch) to find the cause.
  2. Ensure the target canvas has non-zero width/height before `setupBlur`.
  3. Update GPU drivers; FBO completeness bugs are driver-specific.
  4. Report the status code and GL_RENDERER upstream if it persists on compliant hardware.
  5. Reduce frame resolution to rule out max-texture-size limits.

Example fix

// before: setup on an unsized canvas
const state = setupBlur(canvas); // canvas.width === 0

// after: ensure a real size first
canvas.width = Math.max(1, canvas.width);
canvas.height = Math.max(1, canvas.height);
const state = setupBlur(canvas);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the canvas has real dimensions before setup.
const w = Math.max(1, target.width | 0);
const h = Math.max(1, target.height | 0);
target.width = w; target.height = h;
// Optionally probe FBO completeness on a throwaway texture before committing.

Try / catch

try {
  const state = setupBlur(canvas);
} catch (err) {
  if (/framebuffer incomplete/i.test(err.message)) {
    // decode status hex, adjust canvas size / resolution, retry
  } else { throw err; }
}

Prevention

When it happens

Trigger: Fires at line 186-187 when `status !== gl.FRAMEBUFFER_COMPLETE`. The FBO attaches an RGBA/UNSIGNED_BYTE texture sized to `target.width`/`target.height` (clamped to >=1).

Common situations: Zero-sized canvas (`width`/`height` were 0 and clamped to 1, but the attachment still fails on some drivers); driver does not support the chosen internalformat/format combo for render-to-texture; context in a degraded state; the canvas was resized to 0 before setup.

Related errors


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