remotion-dev/remotion · error · Error

Unexpected data left in TRUN box: ${left}

Error message

Unexpected data left in TRUN box: ${left}

What it means

After parsing all TRUN samples (conditionally reading duration, size, flags, composition offset per sample based on the flags bits), the parser checks that exactly zero bytes remain in the box. A non-zero 'left' value means a flag bit indicated a field that wasn't read, sampleCount didn't match actual data, or the box contains trailing/proprietary bytes.

Source

Thrown at packages/media-parser/src/containers/iso-base-media/trun.ts:63

		const sampleCompositionTimeOffset =
			flags & 0x800
				? version === 0
					? iterator.getUint32()
					: iterator.getInt32()
				: null;

		samples.push({
			sampleDuration,
			sampleSize,
			sampleFlags,
			sampleCompositionTimeOffset,
		});
	}

	const currentOffset = iterator.counter.getOffset();
	const left = size - (currentOffset - offset);
	if (left !== 0) {
		throw new Error(`Unexpected data left in TRUN box: ${left}`);
	}

	return {
		type: 'trun-box',
		version,
		sampleCount,
		dataOffset,
		firstSampleFlags,
		samples,
	};
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Dump the trun box: `mp4dump input.mp4 | grep -A20 trun` to see flags, sampleCount, and size.
  2. Re-mux: `ffmpeg -i input.mp4 -c copy -f mp4 -movflags +faststart remuxed.mp4`.
  3. For HLS/DASH, re-fetch the offending segment.
  4. Report upstream if standard trun flags are genuinely unhandled.

Example fix

// before: trun with unhandled flag leaves leftover bytes
ffmpeg -i segment.m4s -c copy remuxed.mp4
// after: trun left === 0
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify trun flag bits are all handled: 0x01 dataOffset, 0x04 firstSampleFlags,
// per-sample: 0x100 duration, 0x200 size, 0x400 flags, 0x800 compositionOffset
const HANDLED_TRUN_FLAGS = 0x01 | 0x04 | 0x100 | 0x200 | 0x400 | 0x800;
function hasUnhandledTrunFlags(flags: number): boolean {
  return (flags & ~HANDLED_TRUN_FLAGS) !== 0;
}

Try / catch

try {
  await parseMedia({src, fields: {dimensions: true}});
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Unexpected data left in TRUN box')) {
    // unhandled trun flag or trailing bytes; re-mux or re-fetch
  } else throw err;
}

Prevention

When it happens

Trigger: size - (currentOffset - offset) != 0 after the sample loop. Common when a trun flag bit is set that the parser doesn't handle, leaving fields unconsumed per sample, or when the declared size overstates the content.

Common situations: Fragmented MP4 with non-standard trun flag combinations, corrupt segments, or files from experimental encoders that pad trun boxes.

Related errors


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