remotion-dev/remotion · error · Error

xing header was parsed wrong: read beyond available data

Error message

xing header was parsed wrong: read beyond available data

What it means

Thrown by parseXing() after consuming the flag-driven fields (numberOfFrames, fileSize, 100-byte TOC, vbrScale) when the running offset has moved past data.length. The comment above the check says extra trailing data is allowed, so the throw fires only when the standard fields themselves overran the buffer — i.e. the flags word claimed fields the buffer could not satisfy.

Source

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

	if (flags & BYTES_FLAG) {
		fileSize = extractI4(data, offset);
		offset += 4;
	}

	if (flags & TOC_FLAG) {
		tableOfContents = data.slice(offset, offset + 100);
		offset += 100;
	}

	if (flags & VBR_SCALE_FLAG) {
		vbrScale = extractI4(data, offset);
		offset += 4;
	}

	// Allow extra data after the standard Xing fields, as some encoders add additional information
	if (offset > data.length) {
		throw new Error('xing header was parsed wrong: read beyond available data');
	}

	return {
		sampleRate,
		numberOfFrames: numberOfFrames ?? null,
		fileSize: fileSize ?? null,
		tableOfContents: tableOfContents
			? Array.from(tableOfContents.slice(0, 100))
			: null,
		vbrScale: vbrScale ?? null,
	};
};

export const getSeekPointInBytes = ({
	fileSize,
	percentBetween0And100,
	tableOfContents,
}: {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Ensure the full first MP3 frame (typically ~417+ bytes for MPEG1) is buffered before calling parseXing() — fetch a larger byte range or read the whole frame.
  2. Re-encode the file so a clean Xing tag is written: ffmpeg -i in.mp3 -c:a libmp3lame -q:a 2 out.mp3
  3. Wrap parseXing() in try/catch and fall back to CBR seek when it fails.

Example fix

// before
const xing = parseXing(partialBuffer);

// after: pass a buffer large enough for the whole first frame
const FRAME_SIZE = mpegVersion === 1 ? 417 : 209;
const xing = parseXing(firstFrame.subarray(0, FRAME_SIZE));
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the first frame buffer is large enough to hold all Xing fields (worst case ~417 bytes for MPEG-1).
const MIN_XING_BUF = 417;
if (firstFrame.length < MIN_XING_BUF) {
  // fetch more bytes / wait for the full frame before calling parseXing
}

Type guard

null

Try / catch

try {
  const xing = parseXing(firstFrame);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('xing header was parsed wrong')) {
    // buffer truncated: re-fetch full first frame and retry, or fall back to CBR
  } else throw err;
}

Prevention

When it happens

Trigger: A Xing header whose flags word is corrupt or whose TOC/fields are truncated (e.g. flags say TOC_FLAG is set but the buffer has fewer than 100 bytes remaining after numberOfFrames/fileSize). Also possible if a wrong xingOffset caused the flags to be read from the wrong position, yielding bogus large flags.

Common situations: Truncated first MP3 frame (e.g. only partial bytes fetched from a network range request); a malformed Xing tag from a buggy encoder; bit-flips in the flags word.

Related errors


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