remotion-dev/remotion · error · Error
Stream does not have a resolution
Error message
Stream does not have a resolution
What it means
Thrown by afterManifestFetch after a stream variant is selected from an HLS master playlist via selectStream(). The selected variant's #EXT-X-STREAM-INF line must include a RESOLUTION attribute (e.g. RESOLUTION=1920x1080). The parser stores this as M3uStream.dimensions and requires it to be non-null at after-manifest-fetch.ts:59 because downstream decoding needs a concrete video frame size to proceed.
Source
Thrown at packages/media-parser/src/containers/m3u/after-manifest-fetch.ts:60
// 2. If streams === null: Single media playlist (has EXT-X-INDEPENDENT-SEGMENTS but no EXT-X-STREAM-INF)
// Both cases should iterate over the current URL as the media playlist
if (!independentSegments || streams === null) {
if (!src) {
throw new Error('No src');
}
m3uState.setSelectedMainPlaylist({
type: 'initial-url',
url: src,
});
return m3uState.setReadyToIterateOverM3u();
}
const selectedPlaylist = await selectStream({streams, fn: selectM3uStreamFn});
if (!selectedPlaylist.dimensions) {
throw new Error('Stream does not have a resolution');
}
m3uState.setSelectedMainPlaylist({
type: 'selected-stream',
stream: selectedPlaylist,
});
const skipAudioTracks =
onAudioTrack === null && canSkipTracks.doFieldsNeedTracks() === false;
const associatedPlaylists = await selectAssociatedPlaylists({
playlists: selectedPlaylist.associatedPlaylists,
fn: selectAssociatedPlaylistsFn,
skipAudioTracks,
});
m3uState.setAssociatedPlaylists(associatedPlaylists);
const playlistUrls = [View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Provide a custom selectM3uStream callback that filters to streams where stream.dimensions !== null before returning an id
- Ensure the master playlist #EXT-X-STREAM-INF lines include RESOLUTION=WxH for every video variant
- If the stream is genuinely audio-only, parse the audio-only media playlist directly instead of through the master-playlist path
Example fix
// before — default callback may pick a resolution-less variant
await parseMedia({src: 'https://cdn.example.com/master.m3u8'});
// after — select a variant that has dimensions
await parseMedia({
src: 'https://cdn.example.com/master.m3u8',
selectM3uStream: ({streams}) => {
const withRes = streams.filter((s) => s.dimensions !== null);
if (withRes.length === 0) throw new Error('No video variants');
return withRes[0].id;
},
}); Defensive patterns
Strategy: validation
Validate before calling
// Pass a custom selectM3uStream that skips resolution-less variants
await parseMedia({
src: 'https://cdn.example.com/master.m3u8',
selectM3uStream: ({streams}) => {
const video = streams.filter((s) => s.dimensions !== null);
if (video.length === 0) {
throw new Error('No video variant with resolution found');
}
return video[0].id;
},
}); Type guard
// Type guard for streams that carry resolution
const hasResolution = (s: M3uStream): s is M3uStream & {dimensions: {width: number; height: number}} =>
s.dimensions !== null; Try / catch
try {
await parseMedia({src, selectM3uStream: myFn});
} catch (e) {
if (e instanceof Error && e.message === 'Stream does not have a resolution') {
// handle: pick a different stream or fall back
}
throw e;
} Prevention
- Always provide a custom selectM3uStream callback that filters on dimensions !== null when parsing master playlists with audio-only variants
- Inspect available streams via the onM3uStreams callback before selection to understand which variants have resolution
When it happens
Trigger: A master playlist where the #EXT-X-STREAM-INF line for the selected variant omits RESOLUTION (common for audio-only variants or streams from encoders that don't set it). Also fired when a custom selectM3uStream callback returns the id of a variant whose dimensions are null — for example selecting an audio-only stream or an I-frame-only variant.
Common situations: Audio-only HLS streams that have no video resolution; playlists from CDNs or encoders (FFmpeg, MediaConvert) that omit RESOLUTION on some variants; a user-provided selectM3uStream callback that picks streams[0] without checking whether dimensions exist.
Related errors
- Expected m3u-text-value
- EXT-X-STREAM-INF directive must have a value
- No moov box found in header segment
- Expected m3u-text-value
- Expected m3u-playlist with src ${src}
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/ef10203634b553fc.
Report an issue: GitHub.