{"record":{"id":"1b36ab6719b294f0","repo":"remotion-dev/remotion","slug":"no-moov-box-found-in-header-segment","errorCode":null,"errorMessage":"No moov box found in header segment","messagePattern":"No moov box found in header segment","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/iso-base-media/get-moov-atom.ts","lineNumber":29,"sourceCode":"\tMediaParserOnVideoTrack,\n} from '../../webcodec-sample-types';\nimport type {IsoBaseMediaBox} from './base-media-box';\nimport type {MoovBox} from './moov/moov';\nimport {processBox} from './process-box';\nimport {getMoovFromFromIsoStructure} from './traversal';\n\nexport const getMoovAtom = async ({\n\tendOfMdat,\n\tstate,\n}: {\n\tstate: ParserState;\n\tendOfMdat: number;\n}): Promise<MoovBox> => {\n\tconst headerSegment = state.m3uPlaylistContext?.mp4HeaderSegment;\n\tif (headerSegment) {\n\t\tconst segment = getMoovFromFromIsoStructure(headerSegment);\n\t\tif (!segment) {\n\t\t\tthrow new Error('No moov box found in header segment');\n\t\t}\n\n\t\treturn segment;\n\t}\n\n\tconst start = Date.now();\n\tLog.verbose(state.logLevel, 'Starting second fetch to get moov atom');\n\tconst {reader} = await state.readerInterface.read({\n\t\tsrc: state.src,\n\t\trange: endOfMdat,\n\t\tcontroller: state.controller,\n\t\tlogLevel: state.logLevel,\n\t\tprefetchCache: state.prefetchCache,\n\t});\n\n\tconst onAudioTrack: MediaParserOnAudioTrack | null = state.onAudioTrack\n\t\t? async ({track, container}) => {\n\t\t\t\tawait registerAudioTrack({","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/iso-base-media/get-moov-atom.ts#L11-L47","documentation":"Thrown by getMoovAtom when the parser is handling an HLS/m3u8 stream that supplies an mp4HeaderSegment (a pre-fetched ISO structure used as the moov source for fMP4 segments), but getMoovFromFromIsoStructure returns null because no top-level moov-box exists in that header segment. The header segment is expected to bootstrap track metadata; if it lacks moov, the parser cannot proceed with fragmented segments.","triggerScenarios":"An HLS playlist whose #EXT-X-MAP or fMP4 initialization segment does not contain a moov atom (e.g. it is actually a raw fMP4 segment without the init, the wrong segment was referenced, or the segment was truncated). Reachable when state.m3uPlaylistContext.mp4HeaderSegment is populated but its boxes array has no 'moov-box' entry.","commonSituations":"Misconfigured HLS origin that points #EXT-X-MAP at a media segment instead of the init segment. CDN caching the wrong segment under the init URL. Partial download of the init segment. Playlist generator bug that omits the init segment.","solutions":["Verify the HLS playlist has a valid #EXT-X-MAP pointing to a real fMP4 initialization segment containing moov.","Fetch the init segment URL directly and inspect it with `ffprobe` to confirm it contains moov.","Regenerate the HLS playlist with a conformant packager (Bento4, ffmpeg HLS muxer, Shaka).","If the init segment is dynamic, ensure your CDN does not cache a media segment in its place."],"exampleFix":"// before\nawait parseMedia({ src: 'https://example.com/stream.m3u8' });\n\n// after\n// Pre-validate the playlist's init segment referenced by #EXT-X-MAP\nconst initRes = await fetch(initSegmentUrl);\nconst initBuf = new Uint8Array(await initRes.arrayBuffer());\nconst hasMoov = String.fromCharCode(...initBuf.subarray(4, 8)) === 'moov'\n  || initBuf.some((_, i) => String.fromCharCode(...initBuf.subarray(i + 4, i + 8)) === 'moov');\nif (!hasMoov) throw new Error('HLS init segment is missing moov; check #EXT-X-MAP');\nawait parseMedia({ src: 'https://example.com/stream.m3u8' });","handlingStrategy":"validation","validationCode":"// Validate the HLS init segment contains moov before handing the playlist to media-parser\nasync function initSegmentHasMoov(initUrl: string): Promise<boolean> {\n  const res = await fetch(initUrl);\n  const buf = new Uint8Array(await res.arrayBuffer());\n  for (let i = 4; i + 4 <= buf.length; i++) {\n    if (buf[i] === 0x6d && buf[i + 1] === 0x6f && buf[i + 2] === 0x6f && buf[i + 3] === 0x76) return true;\n  }\n  return false;\n}","typeGuard":"import type {IsoBaseMediaStructure} from '../../parse-result';\nfunction structureHasMoov(s: IsoBaseMediaStructure | null): boolean {\n  return !!s && s.boxes.some((b) => b.type === 'moov-box');\n}","tryCatchPattern":"try {\n  await parseMedia({ src: playlistUrl });\n} catch (err) {\n  if (/No moov box found in header segment/i.test(String(err?.message))) {\n    throw new Error('HLS init segment (#EXT-X-MAP) is missing moov. Fix the playlist or re-package the stream.');\n  }\n  throw err;\n}","preventionTips":["Always include a valid #EXT-X-MAP init segment that contains moov in HLS playlists you produce.","Fetch the init segment URL yourself and verify it contains a moov box before parsing.","Use a conformant HLS packager (Bento4 mp4dash, ffmpeg HLS, Shaka packager).","Make sure your CDN caches the init segment correctly and never substitutes a media segment."],"tags":["mp4","isobmff","media-parser","hls","m3u8","fmp4","init-segment"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}