remotion-dev/remotion · error · Error

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

Error message

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

What it means

Thrown by the drop-shadow runtime's setFramebufferTexture helper when gl.checkFramebufferStatus returns a value other than FRAMEBUFFER_COMPLETE. The status hex is embedded in the message so the specific cause can be identified (e.g. 0x8cd6 FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 0x8cd5 FRAMEBUFFER_UNSUPPORTED). The runtime attaches an RGBA/UNSIGNED_BYTE texture, so incompleteness usually means zero dimensions, dimensions exceeding GPU limits, or an unsupported format on a non-conformant driver.

Source

Thrown at packages/effects/src/drop-shadow/drop-shadow-runtime.ts:305

	);
};

const setFramebufferTexture = (
	gl: WebGL2RenderingContext,
	framebuffer: WebGLFramebuffer,
	texture: WebGLTexture,
): void => {
	gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
	gl.framebufferTexture2D(
		gl.FRAMEBUFFER,
		gl.COLOR_ATTACHMENT0,
		gl.TEXTURE_2D,
		texture,
		0,
	);
	const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
	if (status !== gl.FRAMEBUFFER_COMPLETE) {
		throw new Error(
			`Drop shadow framebuffer incomplete: 0x${status.toString(16)}`,
		);
	}
};

const setBlurUniforms = ({
	gl,
	uniforms,
	radius,
	width,
	height,
}: {
	readonly gl: WebGL2RenderingContext;
	readonly uniforms: DropShadowState['horizontal'];
	readonly radius: number;
	readonly width: number;
	readonly height: number;
}): void => {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Decode the status hex: 0x8cd6 = incomplete attachment, 0x8cd9 = dimensions mismatch / zero, 0x8cdd = unsupported format.
  2. Ensure composition width and height are always positive integers and never animate to 0.
  3. Keep frame dimensions under gl.getParameter(gl.MAX_TEXTURE_SIZE) (commonly 4096 or 8192 on desktop, 4096 on mobile).
  4. Update GPU drivers if RGBA8 render targets are wrongly rejected.
  5. If the failure comes from a nested effect chain, render through an intermediate Composition at safe dimensions.

Example fix

// before
const w = Math.round(interpolate(frame, [0, 30], [1920, 0]));

// after — keep a 1px floor and stay a power-of-two-safe positive integer
const w = Math.max(1, Math.round(interpolate(frame, [0, 30], [1920, 2])));
Defensive patterns

Strategy: validation

Validate before calling

const safeSize = (n) =>
  typeof n === 'number' && Number.isFinite(n) && n > 0 ? Math.round(n) : null;

const w = safeSize(width);
const h = safeSize(height);
if (w === null || h === null) {
  // skip the drop-shadow pass for this frame instead of crashing
}

Type guard

const MAX = (() => {
  try {
    const gl = document.createElement('canvas').getContext('webgl2');
    return gl ? gl.getParameter(gl.MAX_TEXTURE_SIZE) : 4096;
  } catch {
    return 4096;
  }
})();

const isSafeFrameSize = (w: unknown, h: unknown): boolean =>
  typeof w === 'number' &&
  typeof h === 'number' &&
  Number.isFinite(w) &&
  Number.isFinite(h) &&
  w > 0 &&
  h > 0 &&
  w <= MAX &&
  h <= MAX;

Prevention

When it happens

Trigger: setFramebufferTexture is called per apply() with the shadow textures sized to width x height. If width or height is 0, exceeds MAX_TEXTURE_SIZE, or the driver rejects RGBA/UNSIGNED_BYTE render targets, the framebuffer is incomplete. The hex code in the message pinpoints the failure: 0x8cd6 (attachment), 0x8cd9 (dimensions), 0x8cdd (unsupported).

Common situations: Rendering a composition whose dimensions momentarily collapse to 0 (e.g. a transition that animates scale to 0); rendering at resolutions beyond the GPU's MAX_TEXTURE_SIZE; non-conformant drivers that refuse RGBA8 render targets; nested effects producing zero-size intermediate buffers.

Related errors


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