remotion-dev/remotion · error · Error

The video matting model returned ${result.data.length} bytes

Error message

The video matting model returned ${result.data.length} bytes, but ${expectedLength} RGBA bytes were expected.

What it means

After dimension validation, drawForegroundFrame checks that result.data contains exactly width * height * channels bytes, matching the expected RGBA buffer for ImageData. A mismatch means the model's pixel buffer and its declared geometry disagree, so drawing would read out-of-bounds or produce garbage. The library surfaces both actual and expected byte counts in the message.

Source

Thrown at packages/video-matting/src/video-matting-canvas.ts:87

}: {
	context: VideoMattingCanvasContext;
	result: VideoMattingPipelineResult;
	source: VideoMattingCanvas;
	targetWidth: number;
	targetHeight: number;
}) => {
	if (
		!Number.isInteger(result.width) ||
		result.width <= 0 ||
		!Number.isInteger(result.height) ||
		result.height <= 0
	) {
		throw new Error('The video matting model returned invalid dimensions.');
	}

	const expectedLength = result.width * result.height * result.channels;
	if (result.data.length !== expectedLength) {
		throw new Error(
			`The video matting model returned ${result.data.length} bytes, but ${expectedLength} RGBA bytes were expected.`,
		);
	}

	const imageData = new ImageData(result.data, result.width, result.height);

	context.clearRect(0, 0, targetWidth, targetHeight);
	if (result.width === targetWidth && result.height === targetHeight) {
		context.putImageData(imageData, 0, 0);
	} else {
		const intermediateCanvas = createVideoMattingCanvas({
			width: result.width,
			height: result.height,
		});
		const intermediateContext =
			getVideoMattingCanvasContext(intermediateCanvas);
		intermediateContext.putImageData(imageData, 0, 0);
		context.drawImage(intermediateCanvas, 0, 0, targetWidth, targetHeight);

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Print result.data.length, result.width, result.height and result.channels to see how the buffer mismatches
  2. Ensure the model output tensor is fully copied and converted to RGBA at the same resolution the model reports
  3. Re-run inference when the video resolution changes instead of reusing a stale buffer
  4. If channels !== 4, convert the buffer to RGBA and set channels to 4 before calling
  5. Skip the frame in a try/catch and continue rendering rather than aborting

Example fix

// before
const out = model.infer(frame); // returns RGB buffer
drawForegroundFrame({context, result: {data: out, width: w, height: h, channels: 3}});
// after
const rgba = rgbToRgba(out, w, h);
drawForegroundFrame({context, result: {data: rgba, width: w, height: h, channels: 4}});
Defensive patterns

Strategy: validation

Validate before calling

const expected = result.width * result.height * result.channels;
if (result.data.length !== expected) throw new Error(`Buffer ${result.data.length} != expected ${expected}`);

Type guard

const hasValidBuffer = (r: MattingResult): r is MattingResult =>
  r.data.length === r.width * r.height * r.channels;

Try / catch

try {
  drawForegroundFrame({context, result});
} catch (err) {
  if (err instanceof Error && err.message.includes('RGBA bytes were expected')) {
    console.warn(`Skipping frame: buffer length ${result.data.length} mismatch`);
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: result.data.length !== result.width * result.height * result.channels, e.g. the model returned a buffer sized for a different resolution, a half-finished transfer, or a non-RGBA (channels !== 4) buffer without adjusting the declared channels.

Common situations: Mixing model output resolutions when the source video changes size mid-stream, copying only part of the output tensor into result.data, or a backend returning an RGB (3-channel) buffer while channels is still 4.

Related errors


AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09). Data as JSON: /api/errors/ef47045081ca7e1a. Report an issue: GitHub.