remotion-dev/remotion · error · Error
No moov box found
Error message
No moov box found
What it means
Thrown by getMoovAtom after fetching and parsing the tail of the file (from endOfMdat to contentLength) when none of the parsed top-level boxes is a moov-box. This means the second fetch did not contain the movie metadata — the file either has no moov at all (unplayable), or the fetch read the wrong byte range, or the response was empty/truncated.
Source
Thrown at packages/media-parser/src/containers/iso-base-media/get-moov-atom.ts:134
onlyIfMdatAtomExpected: null,
contentLength: state.contentLength - endOfMdat,
});
if (box.type === 'box') {
boxes.push(box.box);
}
if (iterator.counter.getOffset() + endOfMdat > state.contentLength) {
throw new Error('Read past end of file');
}
if (iterator.counter.getOffset() + endOfMdat === state.contentLength) {
break;
}
}
const moov = boxes.find((b) => b.type === 'moov-box');
if (!moov) {
throw new Error('No moov box found');
}
Log.verbose(
state.logLevel,
`Finished fetching moov atom in ${Date.now() - start}ms`,
);
return moov;
};
View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Confirm the file actually contains a moov atom using `ffprobe` or `mp4info`.
- Ensure your readerInterface correctly serves the requested byte range; test with curl: `curl -r <endOfMdat>-<contentLength> -o tail.bin <url>` and inspect.
- If moov is missing, re-mux with `-movflags faststart` so moov sits at the head and no second fetch is needed.
- Provide an accurate contentLength; an under-sized length will exclude moov from the fetched window.
Example fix
// before
await parseMedia({ src: url });
// after
// Ensure moov is at the front so no second fetch is needed
// On the authoring side:
// ffmpeg -i in.mp4 -c copy -movflags +faststart out.mp4
// Then parse normally
await parseMedia({ src: `${url}?v=faststart` }); Defensive patterns
Strategy: validation
Validate before calling
import {execFileSync} from 'node:child_process';
function fileHasMoov(file: string): boolean {
try {
execFileSync('ffprobe', ['-v', 'error', '-show_format', file], {encoding: 'utf8'});
return true;
} catch { return false; }
} Type guard
import type {IsoBaseMediaBox} from './base-media-box';
function boxesContainMoov(boxes: IsoBaseMediaBox[]): boolean {
return boxes.some((b) => b.type === 'moov-box');
} Try / catch
try {
await parseMedia({ src: url });
} catch (err) {
if (/^No moov box found$/i.test(String(err?.message))) {
throw new Error('No moov atom in the file. Re-mux with ffmpeg -movflags faststart or confirm the byte range served.');
}
throw err;
} Prevention
- Prefer faststart-encoded MP4s so moov is at the head and no second fetch is needed.
- Verify range requests with curl: `curl -r <start>-<end> -o tail.bin <url>` and confirm moov is present.
- Provide an accurate contentLength so the second fetch window actually contains moov.
- Reject files ffprobe cannot read — they almost certainly lack a valid moov.
When it happens
Trigger: Reached in the second-fetch branch (no m3u8 header segment). After reading bytes [endOfMdat, contentLength) and walking top-level boxes, no 'moov-box' was found. Common when contentLength is wrong so the parser reads a window that does not include moov, when the server ignored the range request, or when the file genuinely lacks moov.
Common situations: Files where moov is not at the end (e.g. at the head with ftyp) but the parser still did a second fetch because the first pass did not see it. Truncated uploads missing moov entirely. CDN/range-request misbehavior returning the wrong slice. moov atom stripped by accident.
Related errors
- Expected stsz box in trak box
- Expected stco box in trak box
- Expected stsc box in trak box
- Expected stts box in trak box
- Expected timescale and duration in trak box
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/c6ac5315b6e67f58.
Report an issue: GitHub.