remotion-dev/remotion · error · Error
Expected m3u-text-value
Error message
Expected m3u-text-value
What it means
Thrown by getM3uStreams() at get-streams.ts:63 while iterating a master playlist's boxes. When it encounters an m3u-stream-info box (from #EXT-X-STREAM-INF), it reads the next box expecting it to be an m3u-text-value containing the variant's media playlist URI. If the next box is any other type or is missing (end of array), the master playlist structure is invalid.
Source
Thrown at packages/media-parser/src/containers/m3u/get-streams.ts:63
originalSrc,
readerInterface,
}: {
structure: MediaParserStructureUnstable | null;
originalSrc: ParseMediaSrc;
readerInterface: MediaParserReaderInterface;
}): M3uStream[] | null => {
if (structure === null || structure.type !== 'm3u') {
return null;
}
const boxes: Omit<M3uStream, 'id'>[] = [];
for (let i = 0; i < structure.boxes.length; i++) {
const str = structure.boxes[i];
if (str.type === 'm3u-stream-info') {
const next = structure.boxes[i + 1];
if (next.type !== 'm3u-text-value') {
throw new Error('Expected m3u-text-value');
}
const associatedPlaylists: M3uAssociatedPlaylist[] = [];
if (str.audio) {
const match = structure.boxes.filter((box) => {
return box.type === 'm3u-media-info' && box.groupId === str.audio;
}) as M3uMediaInfo[];
for (const audioTrack of match) {
associatedPlaylists.push({
autoselect: audioTrack.autoselect,
channels: audioTrack.channels,
default: audioTrack.default,
groupId: audioTrack.groupId,
language: audioTrack.language,
name: audioTrack.name,
src: readerInterface.createAdjacentFileSource(View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Verify the master playlist has a media playlist URI on the line immediately after each #EXT-X-STREAM-INF
- Check for network truncation of the manifest response and retry
- Validate the master playlist structure with an HLS conformance checker
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-fetch the master playlist and verify each EXT-X-STREAM-INF has a following URI
const text = await (await fetch(masterUrl)).text();
const lines = text.split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith('#EXT-X-STREAM-INF')) {
if (i + 1 >= lines.length || !lines[i + 1].trim() || lines[i + 1].startsWith('#')) {
throw new Error('Master playlist STREAM-INF without a following URI');
}
}
} Try / catch
try {
await parseMedia({src: masterUrl});
} catch (e) {
if (e instanceof Error && e.message === 'Expected m3u-text-value') {
// master playlist is malformed or truncated
}
throw e;
} Prevention
- Retry on truncation errors as they are often transient
- Validate master playlists from third-party CDNs before relying on them
When it happens
Trigger: A master playlist where #EXT-X-STREAM-INF is the last line with no URI following it; a directive appearing between #EXT-X-STREAM-INF and its URI; a truncated master playlist where the response was cut off after the STREAM-INF line.
Common situations: Truncated HTTP response fetching the master manifest (network timeout, proxy); hand-edited m3u8 with misplaced directives; CDN serving partial content due to range-request issues.
Related errors
- EXT-X-STREAM-INF directive must have a value
- Stream does not have a resolution
- Expected m3u-text-value
- Unexpected end of file
- No moov box found in header segment
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/142ed69cfb156c57.
Report an issue: GitHub.