remotion-dev/remotion · error · Error

Expected box

Error message

Expected box

What it means

Thrown by getIsoBaseMediaChildren when processBox returns a discriminated union value whose `type` is not 'box' (e.g. 'incomplete' or 'skip'). The container walker assumes each child parse within a parent box must complete as a fully parsed box, so any partial/incomplete result is treated as a structural failure. This generally means there were not enough bytes to finish the next child box even though the parent's declared size said more bytes should be present.

Source

Thrown at packages/media-parser/src/containers/iso-base-media/get-children.ts:32

	size: number;
	iterator: BufferIterator;
	logLevel: MediaParserLogLevel;
	onlyIfMoovAtomExpected: OnlyIfMoovAtomExpected | null;
	contentLength: number;
}): Promise<IsoBaseMediaBox[]> => {
	const boxes: IsoBaseMediaBox[] = [];
	const initial = iterator.counter.getOffset();

	while (iterator.counter.getOffset() < size + initial) {
		const parsed = await processBox({
			iterator,
			logLevel,
			onlyIfMoovAtomExpected,
			onlyIfMdatAtomExpected: null,
			contentLength,
		});
		if (parsed.type !== 'box') {
			throw new Error('Expected box');
		}

		boxes.push(parsed.box);
	}

	if (iterator.counter.getOffset() > size + initial) {
		throw new Error(
			`read too many bytes - size: ${size}, read: ${iterator.counter.getOffset() - initial}. initial offset: ${initial}`,
		);
	}

	return boxes;
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Verify the source URL/bytes are complete: re-download and confirm Content-Length matches actual bytes.
  2. If parsing a stream, ensure the iterator is fed until EOF before walking children, or use the streaming parse path that tolerates 'incomplete'.
  3. Re-mux the file with ffmpeg to rebuild box size headers.
  4. Catch the error at the parse boundary and treat the file as unparseable.

Example fix

// before
const boxes = await getIsoBaseMediaChildren({ size, iterator, logLevel, onlyIfMoovAtomExpected, contentLength });

// after
try {
  const boxes = await getIsoBaseMediaChildren({ size, iterator, logLevel, onlyIfMoovAtomExpected, contentLength });
} catch (err) {
  throw new Error(`MP4 structure is truncated or corrupt: ${err instanceof Error ? err.message : err}`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the buffer actually contains the full parent box before walking children
function hasFullBox(buffer: Uint8Array, start: number, declaredSize: number): boolean {
  return start + declaredSize <= buffer.byteLength;
}

Type guard

import type {ProcessBoxResult} from './process-box';
function isCompleteBoxResult(r: ProcessBoxResult): r is { type: 'box'; box: IsoBaseMediaBox } {
  return r.type === 'box';
}

Try / catch

try {
  const boxes = await getIsoBaseMediaChildren({ size, iterator, logLevel, onlyIfMoovAtomExpected, contentLength });
} catch (err) {
  if (/^Expected box$/i.test(String(err?.message))) {
    throw new Error('MP4 is truncated mid-box. Confirm the file is fully downloaded and not corrupt.');
  }
  throw err;
}

Prevention

When it happens

Trigger: A parent box (moov, trak, mdia, stbl, moof, etc.) declares a size larger than the actual payload, so the loop tries to read another child and processBox returns an incomplete result. Reachable on truncated downloads, mid-stream reads where the buffer does not yet contain the full box, or genuine corruption where size fields are wrong.

Common situations: Streaming parses where the network delivered a partial chunk and the parser was given a wrong content length. Files with manually edited size fields. Mid-transfer snapshots. Bugs in box size calculations from third-party muxers.

Related errors


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