remotion-dev/remotion · error

No tracks found

Error message

No tracks found

What it means

defaultGetTracks throws when the parser's track store (parserState.callbacks.tracks.getTracks()) is empty at the moment tracks are required. It is the consumer-facing signal that parsing completed (or was queried) but zero audio/video tracks could be extracted from the container. Note defaultHasallTracks calls defaultGetTracks inside try/catch and merely returns false, so the throw only surfaces when the result is actually demanded.

Source

Thrown at packages/media-parser/src/get-tracks.ts:261

	const moovBox = getMoovBoxFromState({
		structureState: structure,
		isoState,
		mp4HeaderSegment: m3uPlaylistContext?.mp4HeaderSegment ?? null,
		mayUsePrecomputed,
	});
	if (!moovBox) {
		return [];
	}

	return getTracksFromMoovBox(moovBox);
};

export const defaultGetTracks = (
	parserState: ParserState,
): MediaParserTrack[] => {
	const tracks = parserState.callbacks.tracks.getTracks();
	if (tracks.length === 0) {
		throw new Error('No tracks found');
	}

	return tracks;
};

export const defaultHasallTracks = (parserState: ParserState): boolean => {
	try {
		defaultGetTracks(parserState);
		return true;
	} catch {
		return false;
	}
};

export const getTracks = (
	state: ParserState,
	mayUsePrecomputed: boolean,
): MediaParserTrack[] => {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Confirm the src is a real media file with at least one decodable track (`ffprobe src`).
  2. Check the container/codec is supported by @remotion/media-parser; re-encode to H.264/AAC if unsure.
  3. If querying fields conditionally, only request track-dependent fields after verifying the container has tracks.
  4. Wrap parseMedia in try/catch and treat 'No tracks found' as a user-facing 'unsupported file' result rather than a crash.

Example fix

// before
const {tracks} = await parseMedia({src, fields: {tracks: true}});

// after
let tracks;
try {
  ({tracks} = await parseMedia({src, fields: {tracks: true}}));
} catch (e) {
  if (e.message === 'No tracks found') tracks = [];
  else throw e;
}
if (tracks.length === 0) console.warn('Unsupported or empty media:', src);
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe track count with ffprobe before parsing
import {execFileSync} from 'node:child_process';
function hasTracks(path: string): boolean {
  try {
    const out = execFileSync('ffprobe', ['-v','error','-show_entries','stream=codec_type','-of','csv=p=0', path], {stdio: 'pipe'}).toString();
    return out.trim().length > 0;
  } catch { return false; }
}

Try / catch

let tracks = [];
try {
  ({tracks} = await parseMedia({src, fields: {tracks: true}}));
} catch (e) {
  if (e instanceof Error && e.message === 'No tracks found') tracks = [];
  else throw e;
}
if (tracks.length === 0) console.warn('No usable tracks in', src);

Prevention

When it happens

Trigger: Calling parseMedia (or any field that requires tracks) on a container the parser finished scanning without registering any track: e.g. a WebM/Matroska with no audio/video, an MP4 whose trak boxes all failed makeBaseMediaTrack, or a stream that ended before any track header arrived. Also triggered if hasAllTracks is false and code still demands getTracks().

Common situations: Passing a non-media file (e.g. a .txt renamed .mp4), a metadata-only MP4, an HLS playlist whose init segment lacks tracks, or a media file using an unsupported codec that makeBaseMediaTrack skips.

Related errors


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