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
- Confirm the src is a real media file with at least one decodable track (`ffprobe src`).
- Check the container/codec is supported by @remotion/media-parser; re-encode to H.264/AAC if unsure.
- If querying fields conditionally, only request track-dependent fields after verifying the container has tracks.
- 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
- Treat 'No tracks found' as an expected unsupported-file outcome, not a crash.
- Pre-screen uploads with ffprobe to ensure at least one audio or video stream.
- Re-encode exotic codecs to H.264/AAC before parsing.
- Only request track-dependent fields when you know the container is supported.
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
- Invalid AAC codec private length
- Could not find video codec
- Invalid table ID: ${tableId}
- Invalid section length
- Unexpected PES packet start code: ${ident.toString(16)}
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/bcab373590293894.
Report an issue: GitHub.