{"record":{"id":"d229d085763679b8","repo":"remotion-dev/remotion","slug":"expected-tkhd-box-in-trak-box-d229d0","errorCode":null,"errorMessage":"Expected tkhd box in trak box","messagePattern":"Expected tkhd box in trak box","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/iso-base-media/make-track.ts","lineNumber":54,"sourceCode":"import {findTrackMediaTimeOffsetInTrackTimescale} from './mdat/get-editlist';\nimport type {TrakBox} from './trak/trak';\nimport {getTkhdBox, getVideoDescriptors} from './traversal';\n\nexport const makeBaseMediaTrack = (\n\ttrakBox: TrakBox,\n\tstartTimeInSeconds: number,\n):\n\t| MediaParserVideoTrack\n\t| MediaParserAudioTrack\n\t| MediaParserOtherTrack\n\t| null => {\n\tconst tkhdBox = getTkhdBox(trakBox);\n\n\tconst videoDescriptors = getVideoDescriptors(trakBox);\n\tconst timescaleAndDuration = getTimescaleAndDuration(trakBox);\n\n\tif (!tkhdBox) {\n\t\tthrow new Error('Expected tkhd box in trak box');\n\t}\n\n\tif (!timescaleAndDuration) {\n\t\tthrow new Error('Expected timescale and duration in trak box');\n\t}\n\n\tif (trakBoxContainsAudio(trakBox)) {\n\t\tconst numberOfChannels = getNumberOfChannelsFromTrak(trakBox);\n\t\tif (numberOfChannels === null) {\n\t\t\tthrow new Error('Could not find number of channels');\n\t\t}\n\n\t\tconst sampleRate = getSampleRate(trakBox);\n\t\tif (sampleRate === null) {\n\t\t\tthrow new Error('Could not find sample rate');\n\t\t}\n\n\t\tconst {codecString, description} = getAudioCodecStringFromTrak(trakBox);","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/iso-base-media/make-track.ts#L36-L72","documentation":"Thrown by makeBaseMediaTrack when getTkhdBox(trakBox) returns null during track construction. The tkhd (Track Header) box carries trackId, dimensions, and timing — all required to materialize a MediaParserTrack. ISO/IEC 14496-12 mandates tkhd in every trak, so a missing tkhd indicates a malformed file or a parsing bug that misclassified the box.","triggerScenarios":"Reached for every trak in the moov during the initial track-registration pass. Fires when a trak has no tkhd-box child, or when the tkhd was parsed under a different type due to version/flag misreading. Distinct from the seeking-path tkhd errors because this blocks track creation entirely.","commonSituations":"Corrupt moov atoms. Files from non-standard muxers. Truncated uploads where moov is partially present. Test fixtures with synthetic traks missing tkhd.","solutions":["Re-mux with `ffmpeg -i in.mp4 -c copy -movflags faststart out.mp4` to regenerate tkhd.","Validate the file with `ffprobe -show_streams`; reject files that report a malformed track header.","Catch the error around the parse call and present a 'corrupt file' message to the user.","If authoring traks programmatically, ensure tkhd is the first child of every trak."],"exampleFix":"// before\nawait parseMedia({ src: file });\n\n// after\ntry {\n  await parseMedia({ src: file });\n} catch (err) {\n  if (/Expected tkhd box/i.test(String(err?.message))) {\n    throw new Error('MP4 is missing a required track header (tkhd). The file is corrupt; re-mux it with ffmpeg.');\n  }\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":"import type {TrakBox} from './trak/trak';\nimport {getTkhdBox} from './traversal';\nfunction trakHasTkhdForTrack(trakBox: TrakBox): boolean {\n  return getTkhdBox(trakBox) !== null;\n}","typeGuard":"import type {TrakBox} from './trak/trak';\nimport type {TkhdBox} from './tkhd';\nimport {getTkhdBox} from './traversal';\nfunction hasTkhdBox(trakBox: TrakBox): boolean {\n  return getTkhdBox(trakBox) !== null;\n}","tryCatchPattern":"try {\n  await parseMedia({ src: file });\n} catch (err) {\n  if (/Expected tkhd box in trak box/i.test(String(err?.message))) {\n    throw new Error('MP4 track is missing its header (tkhd). The file is corrupt; re-mux with ffmpeg -movflags faststart.');\n  }\n  throw err;\n}","preventionTips":["Re-mux user uploads with faststart to rebuild the full trak structure.","Run ffprobe as an upload-validation gate and reject malformed files.","Catch tkhd errors centrally and present a single 'corrupt file' message.","Ensure programmatic trak authors always include a tkhd child."],"tags":["mp4","isobmff","media-parser","trak","tkhd","corrupt-file","track-construction"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}