remotion-dev/remotion · error · Error
Expected tkhd box in trak box
Error message
Expected tkhd box in trak box
What it means
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.
Source
Thrown at packages/media-parser/src/containers/iso-base-media/make-track.ts:54
import {findTrackMediaTimeOffsetInTrackTimescale} from './mdat/get-editlist';
import type {TrakBox} from './trak/trak';
import {getTkhdBox, getVideoDescriptors} from './traversal';
export const makeBaseMediaTrack = (
trakBox: TrakBox,
startTimeInSeconds: number,
):
| MediaParserVideoTrack
| MediaParserAudioTrack
| MediaParserOtherTrack
| null => {
const tkhdBox = getTkhdBox(trakBox);
const videoDescriptors = getVideoDescriptors(trakBox);
const timescaleAndDuration = getTimescaleAndDuration(trakBox);
if (!tkhdBox) {
throw new Error('Expected tkhd box in trak box');
}
if (!timescaleAndDuration) {
throw new Error('Expected timescale and duration in trak box');
}
if (trakBoxContainsAudio(trakBox)) {
const numberOfChannels = getNumberOfChannelsFromTrak(trakBox);
if (numberOfChannels === null) {
throw new Error('Could not find number of channels');
}
const sampleRate = getSampleRate(trakBox);
if (sampleRate === null) {
throw new Error('Could not find sample rate');
}
const {codecString, description} = getAudioCodecStringFromTrak(trakBox);View on GitHub (pinned to 78fe4bb3fd)
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.
Example fix
// before
await parseMedia({ src: file });
// after
try {
await parseMedia({ src: file });
} catch (err) {
if (/Expected tkhd box/i.test(String(err?.message))) {
throw new Error('MP4 is missing a required track header (tkhd). The file is corrupt; re-mux it with ffmpeg.');
}
throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
import type {TrakBox} from './trak/trak';
import {getTkhdBox} from './traversal';
function trakHasTkhdForTrack(trakBox: TrakBox): boolean {
return getTkhdBox(trakBox) !== null;
} Type guard
import type {TrakBox} from './trak/trak';
import type {TkhdBox} from './tkhd';
import {getTkhdBox} from './traversal';
function hasTkhdBox(trakBox: TrakBox): boolean {
return getTkhdBox(trakBox) !== null;
} Try / catch
try {
await parseMedia({ src: file });
} catch (err) {
if (/Expected tkhd box in trak box/i.test(String(err?.message))) {
throw new Error('MP4 track is missing its header (tkhd). The file is corrupt; re-mux with ffmpeg -movflags faststart.');
}
throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Corrupt moov atoms. Files from non-standard muxers. Truncated uploads where moov is partially present. Test fixtures with synthetic traks missing tkhd.
Related errors
- Expected tkhd box in trak box
- Expected timescale and duration in trak box
- Expected tkhd box in trak box
- Expected stsz box in trak box
- Expected stco box in trak box
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/d229d085763679b8.
Report an issue: GitHub.