remotion-dev/remotion · error · Error

Invalid Xing header

Error message

Invalid Xing header

What it means

Thrown by parseXing() when the 4 ASCII bytes at the computed xingOffset do not equal 'Xing'. The offset is derived from the MPEG version and mode bits in the first frame header, so a mismatch means either the frame is not a VBR info frame or the header bits led the parser to the wrong location. This is the parser asserting it was promised a Xing/VBR header but did not find one.

Source

Thrown at packages/media-parser/src/containers/mp3/parse-xing.ts:53

	if (h_id) {
		// mpeg1
		if (h_mode !== 3) {
			xingOffset += 32 + 4;
		} else {
			xingOffset += 17 + 4;
		}
	} else if (h_mode !== 3) {
		xingOffset += 17 + 4;
	} else {
		xingOffset += 9 + 4;
	}

	const expectXing = new TextDecoder('utf8').decode(
		data.slice(xingOffset, xingOffset + 4),
	);
	if (expectXing !== 'Xing') {
		throw new Error('Invalid Xing header');
	}

	let sampleRate = SAMPLE_RATES[h_sr_index];
	if (h_id === 0) {
		sampleRate >>= 1;
	}

	let offset = xingOffset + 4;

	const flags = extractI4(data, offset);
	offset += 4;

	let numberOfFrames;
	let fileSize;
	let tableOfContents;
	let vbrScale;

	if (flags & FRAMES_FLAG) {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Confirm the file actually has a Xing tag (ffmpeg -i file.mp3 will show '.Container: ...' / Xing metadata); if it is CBR, use the CBR seek path instead of VBR.
  2. If the tag says 'Info' (CBR files use 'Info' marker), re-encode with a VBR encoder so a real 'Xing' tag is written: ffmpeg -i in.mp3 -c:a libmp3lame -q:a 2 out.mp3
  3. Guard parseXing() calls with a try/catch and fall back to CBR seek logic when it throws.

Example fix

// before
const xing = parseXing(firstFrameBytes);

// after
let xing: XingData | null = null;
try {
  xing = parseXing(firstFrameBytes);
} catch {
  // not a VBR file; fall back to CBR seek
  xing = null;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check the 4 bytes at the expected Xing offset before calling parseXing.
function hasXingTag(firstFrame: Uint8Array): boolean {
  const h_id = (firstFrame[1] >> 3) & 1;
  const h_mode = (firstFrame[3] >> 6) & 3;
  let off = 0;
  if (h_id) off = h_mode !== 3 ? 32 + 4 : 17 + 4;
  else off = h_mode !== 3 ? 17 + 4 : 9 + 4;
  return (
    firstFrame.length >= off + 4 &&
    new TextDecoder().decode(firstFrame.subarray(off, off + 4)) === 'Xing'
  );
}

Type guard

null

Try / catch

let xing: XingData | null;
try {
  xing = parseXing(firstFrame);
} catch {
  xing = null; // not a VBR/Xing frame; use CBR path
}

Prevention

When it happens

Trigger: parseXing() is invoked on a buffer that is not actually a Xing-tagged frame: CBR MP3s (no Xing tag), a frame whose side-info length differs from the computed offset, or a buffer that starts mid-stream. Also triggered if the caller assumes VBR but the file is CBR.

Common situations: Passing a CBR-encoded MP3 into a VBR code path; truncated first frame; MP3 produced by an encoder that writes 'Info' instead of 'Xing' (the parser only matches 'Xing'); mis-detected container.

Related errors


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