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.
Solutions
- Verify the source URL/bytes are complete: re-download and confirm Content-Length matches actual bytes.
- If parsing a stream, ensure the iterator is fed until EOF before walking children, or use the streaming parse path that tolerates 'incomplete'.
- Re-mux the file with ffmpeg to rebuild box size headers.
- 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
- Confirm Content-Length and actual byte count match before parsing.
- For streamed sources, wait until EOF or use a streaming-tolerant parse path that retries on 'incomplete'.
- Catch structural errors at the public API boundary and present a single 'unsupported file' message.
- Re-mux suspect files with ffmpeg before parsing.
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
- expected 0 bytes
- expected 0 bytes
- Expected sample descriptions, got
- Expected stco box in trak box
- Expected stsc box in trak box
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/c1ac7cf6220d8ad8.
Report an issue: GitHub.
Appendix: 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)