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
- 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.
- 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
- 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
- Use the VBR/Xing path only after confirming a 'Xing' marker is present.
- Remember CBR MP3s use the 'Info' marker, which parseXing does not accept.
- Fall back to CBR seek when parseXing throws.
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
- xing header was parsed wrong: read beyond available data
- No MP3 info
- Cannot get duration of VBR MP3 file - no frames
- Cannot get duration of VBR MP3 file - no sample rate
- MP3 files with VBRI are currently unsupported because we hav
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/b29a0904f6c43612.
Report an issue: GitHub.