remotion-dev/remotion · error · Error

Expected tkhd box in trak box

Error message

Expected tkhd box in trak box

What it means

Thrown by getSeekingByteFromFragmentedMp4 (after locating the correct trakBox by trackId) when getTkhdBox(trakBox) returns null. The targeted trak lacks a tkhd child, so the parser cannot read timescale/duration/trackId needed for sample position computation in fragmented mode. tkhd is mandatory in every trak per ISO/IEC 14496-12.

Source

Thrown at packages/media-parser/src/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.ts:73

	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),
		});

	Log.trace(
		logLevel,
		'Fragmented MP4 - Checking if we have seeking info for this time range',

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Re-mux the init segment with a conformant packager (ffmpeg, Shaka, Bento4).
  2. Validate the init segment with `ffprobe` and reject if tkhd is missing.
  3. Catch the error at the seek boundary and report 'corrupt init segment'.
  4. Ensure the moov is fully parsed before exposing its traks to the seek logic.

Example fix

// before
await parser.seek(time);

// after
try {
  await parser.seek(time);
} catch (err) {
  if (/Expected tkhd box/i.test(String(err?.message))) {
    throw new Error('fMP4 init segment is missing a track header (tkhd). Re-mux the init segment.');
  }
  throw err;
}
Defensive patterns

Strategy: type-guard

Validate before calling

import {getTkhdBox} from './traversal';
import type {TrakBox} from './trak/trak';
function targetedTrakHasTkhd(trakBox: TrakBox): boolean {
  return getTkhdBox(trakBox) !== null;
}

Type guard

import type {TrakBox} from './trak/trak';
import {getTkhdBox} from './traversal';
function trakHasTkhd(trakBox: TrakBox): boolean {
  return getTkhdBox(trakBox) !== null;
}

Try / catch

try {
  await parser.seek(time);
} catch (err) {
  if (/Expected tkhd box in trak box/i.test(String(err?.message))) {
    throw new Error('fMP4 trak is missing its tkhd header; init segment is corrupt.');
  }
  throw err;
}

Prevention

When it happens

Trigger: A fragmented MP4 whose moov contains a trak that matched the trackId but has no tkhd box (or whose tkhd was parsed as another type). Reachable on the seeking path right after a successful getTrakBoxByTrackId.

Common situations: Corrupt fMP4 init segment with a malformed trak. Files produced by non-conformant DASH packagers. Truncated init segments. Race where a partially parsed moov is exposed before tkhd is read.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/0232f5f872cbe8ba. Report an issue: GitHub.