remotion-dev/remotion · error · Error
Expected remaining bytes to be 0, got ${remaining}
Error message
Expected remaining bytes to be 0, got ${remaining} What it means
Thrown at the end of parseMdhd() (media header box). After reading all defined mdhd fields for the box's version, leftover bytes remain: size - (bytesConsumed) !== 0. The box's declared size does not match the byte count the spec mandates, so the parser treats the box as malformed and aborts.
Source
Thrown at packages/media-parser/src/containers/iso-base-media/mdhd.ts:46
// creation time
const creationTime =
version === 1 ? Number(data.getUint64()) : data.getUint32();
// modification time
const modificationTime =
version === 1 ? Number(data.getUint64()) : data.getUint32();
const timescale = data.getUint32();
const duration = version === 1 ? data.getUint64() : data.getUint32();
const language = data.getUint16();
// quality
const quality = data.getUint16();
const remaining = size - (data.counter.getOffset() - fileOffset);
if (remaining !== 0) {
throw new Error(`Expected remaining bytes to be 0, got ${remaining}`);
}
return {
type: 'mdhd-box',
duration: Number(duration),
timescale,
version,
language,
quality,
creationTime,
modificationTime,
};
};
View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Re-mux with a compliant tool: ffmpeg -i in.mp4 -c copy out.mp4 (this rebuilds boxes with correct sizes).
- Validate with MP4Box -info in.mp4 or ffprobe; both flag box-size inconsistencies.
- Migrate to @remotion/mediabunny (parseMedia is deprecated) which may tolerate the mismatch.
- Obtain a fresh copy of the source file if you suspect download corruption.
Example fix
// before
const {durationInSeconds} = await parseMedia({src, reader: nodeReader});
// after
try {
const {durationInSeconds} = await parseMedia({src, reader: nodeReader});
} catch (err) {
if (err instanceof Error && /Expected remaining bytes to be 0/.test(err.message)) {
// mdhd box size mismatch — re-mux with ffmpeg to rebuild boxes
} else throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Have ffprobe/MP4Box sanity-check the file before parsing; box-size
// inconsistencies surface there as warnings/errors:
// MP4Box -info in.mp4
// ffprobe -v warning in.mp4
import {execFileSync} from 'node:child_process';
function fileLooksIntact(file: string): boolean {
try {
execFileSync('ffprobe', ['-v','warning','-hide_banner', file], {encoding: 'utf8', stdio:'pipe'});
return true;
} catch { return false; }
} Type guard
// mdhd box correctness is a deep binary property; not type-guardable by the caller. // => typeGuard: null
Try / catch
try {
await parseMedia({src, reader: nodeReader});
} catch (err) {
if (err instanceof Error && /Expected remaining bytes to be 0/.test(err.message)) {
// mdhd size mismatch — re-mux with ffmpeg
} else {
throw err;
}
} Prevention
- Re-mux suspect files with ffmpeg to rebuild correctly-sized boxes.
- Validate with MP4Box -info / ffprobe before parsing.
- Migrate to @remotion/mediabunny (parseMedia is deprecated).
- Keep a try/catch around parseMedia() for untrusted inputs.
When it happens
Trigger: parseMedia({src}) on an MP4/MOV/M4A whose mdhd box size is inconsistent with its version-0 or version-1 field layout — e.g. an mdhd with extra trailing bytes, a version this parser did not account for, or a size field that was corrupted/truncated.
Common situations: Files written by non-compliant muxers that pad or truncate boxes; edited/patched MP4s; corrupted downloads where the mdhd size field is wrong.
Related errors
- expected 0 bytes ${bytesRemaining}
- Expected timescale and duration in trak box
- read too many bytes - size: ${size}, read: ${iterator.counte
- Expected timescale and duration in trak box
- Could not find number of channels
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/0b32df7a04e07112.
Report an issue: GitHub.