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

  1. Verify the master playlist has a media playlist URI on the line immediately after each #EXT-X-STREAM-INF
  2. Check for network truncation of the manifest response and retry
  3. 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

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


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