remotion-dev/remotion · error · Error
No trak box found
Error message
No trak box found
What it means
Thrown by getSeekingByteFromFragmentedMp4 when getTrakBoxByTrackId(moov, firstTrack.trackId) returns null. The moov atom parsed fine and a track was registered with a given trackId, but no trak inside moov has a matching tkhd.trackId. This indicates a mismatch between the track objects the parser exposes and the actual trak boxes in the moov — typically a state inconsistency or a moov that was replaced between parse and seek.
Source
Thrown at packages/media-parser/src/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.ts:68
if (!firstTrack) {
throw new Error('no video and no audio tracks');
}
const moov = getMoovBoxFromState({
structureState: structure,
isoState,
mp4HeaderSegment,
mayUsePrecomputed: true,
});
if (!moov) {
throw new Error('No moov atom found');
}
const trakBox = getTrakBoxByTrackId(moov, firstTrack.trackId);
if (!trakBox) {
throw new Error('No trak box found');
}
const tkhdBox = getTkhdBox(trakBox);
if (!tkhdBox) {
throw new Error('Expected tkhd box in trak box');
}
const isComplete = areSamplesComplete({
moofBoxes: info.moofBoxes,
tfraBoxes: info.tfraBoxes,
});
const {samplePositions: samplePositionsArray} =
collectSamplePositionsFromMoofBoxes({
moofBoxes: info.moofBoxes,
tkhdBox,
isComplete,
trexBoxes: getTrexBoxes(moov),View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Reset/rebuild the tracks array whenever the moov is reloaded (e.g. on HLS variant switch).
- Validate that every track.trackId corresponds to a trak in the current moov before seeking.
- If the source is adaptive, pin to a single variant during a seek operation.
- Ensure tkhd.trackId is parsed correctly; if 0 or NaN, treat the file as corrupt.
Example fix
// before
await parser.seek(time);
// after
const trakIds = new Set(getTraks(moov).map((t) => getTkhdBox(t)?.trackId));
if (!tracks.every((t) => trakIds.has(t.trackId))) {
// moov changed under us; rebuild tracks before seeking
await reloadTracks();
}
await parser.seek(time); Defensive patterns
Strategy: validation
Validate before calling
import type {MoovBox} from './moov/moov';
import {getTraks, getTkhdBox} from './traversal';
function moovHasTrackId(moov: MoovBox, trackId: number): boolean {
return getTraks(moov).some((t) => getTkhdBox(t)?.trackId === trackId);
} Type guard
import type {MoovBox} from './moov/moov';
import {getTraks, getTkhdBox} from './traversal';
function moovHasTrakForTrack(moov: MoovBox, trackId: number): boolean {
return getTraks(moov).some((t) => getTkhdBox(t)?.trackId === trackId);
} Try / catch
try {
await parser.seek(time);
} catch (err) {
if (/No trak box found/i.test(String(err?.message))) {
// moov changed under us; rebuild tracks then retry
await reloadTracksFromCurrentMoov();
return parser.seek(time);
}
throw err;
} Prevention
- Rebuild the tracks array whenever the moov is reloaded (e.g. HLS variant switch).
- Pin a single variant during an active seek operation.
- Validate trackId against the current moov before seeking.
- Discard stale track references after moov replacement.
When it happens
Trigger: A track object in state.tracks carries a trackId that does not correspond to any trak in the current moov (e.g. moov was re-fetched or swapped, e.g. across HLS variant switches). Also reachable if trackId is 0 or unset because tkhd was malformed during track construction.
Common situations: Adaptive streaming where the active variant's moov changed but the track list still references the old trackId. Damaged moov where tkhd.trackId was misread. Custom readerInterface returning different bytes for the same range across calls. Race during variant switch.
Related errors
- no video and no audio tracks
- No moov atom found
- Expected tkhd box in trak box
- No video section defined
- Expected stco box in trak box
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/2cbbcb7180a2ce50.
Report an issue: GitHub.