{"record":{"id":"0872d5991d692118","repo":"remotion-dev/remotion","slug":"no-moov-atom-found","errorCode":null,"errorMessage":"No moov atom found","messagePattern":"No moov atom found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.ts","lineNumber":62,"sourceCode":"\tmp4HeaderSegment: IsoBaseMediaStructure | null;\n}): Promise<SeekResolution> => {\n\tconst firstVideoTrack = tracks.find((t) => t.type === 'video');\n\n\t// If there is both video and audio, seek based on video, but if not then audio is also okay\n\tconst firstTrack = firstVideoTrack ?? tracks.find((t) => t.type === 'audio');\n\n\tif (!firstTrack) {\n\t\tthrow new Error('no video and no audio tracks');\n\t}\n\n\tconst moov = getMoovBoxFromState({\n\t\tstructureState: structure,\n\t\tisoState,\n\t\tmp4HeaderSegment,\n\t\tmayUsePrecomputed: true,\n\t});\n\tif (!moov) {\n\t\tthrow new Error('No moov atom found');\n\t}\n\n\tconst trakBox = getTrakBoxByTrackId(moov, firstTrack.trackId);\n\n\tif (!trakBox) {\n\t\tthrow new Error('No trak box found');\n\t}\n\n\tconst tkhdBox = getTkhdBox(trakBox);\n\tif (!tkhdBox) {\n\t\tthrow new Error('Expected tkhd box in trak box');\n\t}\n\n\tconst isComplete = areSamplesComplete({\n\t\tmoofBoxes: info.moofBoxes,\n\t\ttfraBoxes: info.tfraBoxes,\n\t});\n","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.ts#L44-L80","documentation":"Thrown by getSeekingByteFromFragmentedMp4 when getMoovBoxFromState returns null while resolving a fragmented MP4 seek. Unlike the progressive path, fragmented MP4 keeps moov in parser state (and optionally the precomputed cache or mp4HeaderSegment); if none of those sources has it yet, the seek cannot be resolved. This is usually a timing/ordering issue rather than file corruption.","triggerScenarios":"Seek is requested before the moov atom has been parsed into state. Reachable when the m3u8 init segment has not been fully processed, when precomputed moov is disallowed (mayUsePrecomputed=false in some other call path), or when the moov fetch is still in flight. The check fires after confirming a track exists but before extracting its trak.","commonSituations":"Calling seek too early in a streaming/fMP4 parse. Init segment still downloading. A reader that delivers fragments before the init. State not yet populated because the moov-bearing box was just queued.","solutions":["Wait for the parser to emit its first track (onVideoTrack/onAudioTrack) before seeking — that guarantees moov is loaded.","If using an m3u8 source, ensure the init segment (#EXT-X-MAP) is reachable.","Retry the seek after a short delay or on the next progress event; this is often transient.","If persistent, validate the source exposes moov in its init segment via `ffprobe`."],"exampleFix":"// before\nawait parser.seek(time);\n\n// after\nlet moovReady = false;\nawait parseMedia({\n  src,\n  onVideoTrack: () => { moovReady = true; },\n  onAudioTrack: () => { moovReady = true; },\n});\nif (!moovReady) throw new Error('Cannot seek: moov not loaded yet');\nawait parser.seek(time);","handlingStrategy":"retry","validationCode":"// Track when moov becomes available via the first onVideoTrack/onAudioTrack callback\nlet moovReady = false;\nawait parseMedia({ src, onVideoTrack: () => { moovReady = true; }, onAudioTrack: () => { moovReady = true; } });\nif (!moovReady) throw new Error('moov not loaded');","typeGuard":"import type {StructureState} from '../../state/structure';\nimport type {IsoBaseMediaState} from '../../state/iso-base-media/iso-state';\nimport {getMoovBoxFromState} from './traversal';\nfunction moovIsAvailable(structure: StructureState, iso: IsoBaseMediaState, header: any): boolean {\n  return getMoovBoxFromState({ structureState: structure, isoState: iso, mp4HeaderSegment: header, mayUsePrecomputed: true }) !== null;\n}","tryCatchPattern":"try {\n  await parser.seek(time);\n} catch (err) {\n  if (/No moov atom found/i.test(String(err?.message))) {\n    // transient: retry after the next progress event\n    parser.once('progress', () => parser.seek(time));\n    return;\n  }\n  throw err;\n}","preventionTips":["Defer seeking until the first onVideoTrack or onAudioTrack callback has fired.","For HLS sources, ensure the init segment is reachable and fully downloaded.","Treat 'No moov atom found' during fMP4 seeking as transient and retry.","Persist a 'moov ready' flag and gate seek UI on it."],"tags":["mp4","isobmff","media-parser","fmp4","seeking","moov","timing"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}