remotion-dev/remotion · error

Expected mvhd-box

Error message

Expected mvhd-box

What it means

Thrown by getDuration() as a defensive type check after getMvhdBox(moovBox) returns a non-null value whose type is not 'mvhd-box'. In practice the moov box is expected to contain exactly one well-formed movie header; reaching this throw means the box parser produced a node of the wrong type, indicating corrupt data or an internal invariant violation rather than normal user input.

Source

Thrown at packages/media-parser/src/get-duration.ts:93

	const moofBoxes = getMoofBoxes(structure.boxes);
	const mfra = parserState.iso.mfra.getIfAlreadyLoaded();
	const tfraBoxes = deduplicateTfraBoxesByOffset([
		...(mfra ? getTfraBoxesFromMfraBoxChildren(mfra) : []),
		...getTfraBoxes(structure.boxes),
	]);

	if (!areSamplesComplete({moofBoxes, tfraBoxes})) {
		return null;
	}

	const mvhdBox = getMvhdBox(moovBox);

	if (!mvhdBox) {
		return null;
	}

	if (mvhdBox.type !== 'mvhd-box') {
		throw new Error('Expected mvhd-box');
	}

	if (mvhdBox.durationInSeconds > 0) {
		return mvhdBox.durationInSeconds;
	}

	const tracks = getTracks(parserState, true);

	const allSamples = tracks.map((t) => {
		const {originalTimescale: ts} = t;

		const trakBox = getTrakBoxByTrackId(moovBox, t.trackId);

		if (!trakBox) {
			return null;
		}

		const {samplePositions, isComplete} = getSamplePositionsFromTrack({

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Re-fetch or re-mux the source file; a conformant MP4 should not reach this branch.
  2. Wrap duration parsing in try/catch and fall back to a sample-based duration calculation or null duration.
  3. Report the file to the library maintainers with the structure dump, since this guard usually signals an internal invariant break.

Example fix

// before
const duration = getDuration(parserState);

// after
let duration;
try {
  duration = getDuration(parserState);
} catch (err) {
  console.warn('Could not read mvhd duration', err);
  duration = null;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const mvhd = getMvhdBox(moovBox);
if (mvhd && mvhd.type === 'mvhd-box' && mvhd.durationInSeconds > 0) { /* safe */ }

Type guard

const isMvhdBox = (b): b is MvhdBox => b?.type === 'mvhd-box';

Try / catch

try { getDuration(parserState); } catch (e) { if (e.message === 'Expected mvhd-box') { /* corrupt moov, fall back to null duration */ } else throw e; }

Prevention

When it happens

Trigger: A malformed MP4 where the moov contains a box that getMvhdBox matched but is not actually typed mvhd-box. Extremely rare; usually points to a parser bug or bit-flipped box header.

Common situations: Processing damaged MP4 files. Encountering edge cases in fragmented MP4s where the moov is reconstructed from segments. After partial writes or truncated downloads that nonetheless yielded a box.

Related errors


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