remotion-dev/remotion · error · Error

Unknown directive ${directive}. Value: ${value}

Error message

Unknown directive ${directive}. Value: ${value}

What it means

Thrown by parseM3uDirective() at parse-directive.ts:159 as the fallback for any #-prefixed line that does not match any known directive. The parser recognizes a fixed set of HLS directives; any other line starting with '#' that is not '#EXTM3U' or one of the known EXT-* directives falls through to this throw. Note: RFC 8216 section 4.2 states clients SHOULD ignore unrecognized EXT-* tags, so this behavior is stricter than the spec requires.

Source

Thrown at packages/media-parser/src/containers/m3u/parse-directive.ts:159

			value: p.URI,
		};
	}

	if (directive === '#EXT-X-PROGRAM-DATE-TIME') {
		if (!value) {
			throw new Error('#EXT-X-PROGRAM-DATE-TIME directive must have a value');
		}

		// Store the raw ISO 8601 date-time string without validation.
		// This directive associates media segments with absolute dates but
		// doesn't affect parsing of tracks, dimensions, or other metadata.
		return {
			type: 'm3u-program-date-time',
			dateTime: value,
		};
	}

	throw new Error(`Unknown directive ${directive}. Value: ${value}`);
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Identify the unrecognized directive from the error message and check if it can be removed from the source playlist
  2. If the directive is #EXT-X-KEY (encryption), the stream requires decryption keys that this parser may not support — use a different tool or remove encryption
  3. Pre-fetch the m3u8 text and filter out unsupported directive lines before passing the src to parseMedia

Example fix

// before — playlist contains #EXT-X-KEY which the parser doesn't handle
#EXT-X-KEY:METHOD=AES-128,URI="key.bin"
#EXTINF:10.0,
segment0.ts

// after — pre-fetch and filter unsupported directives, then parse from a Blob
const text = await (await fetch(url)).text();
const filtered = text
  .split('\n')
  .filter((line) => !line.startsWith('#EXT-X-KEY'))
  .join('\n');
await parseMedia({src: new Blob([filtered], {type: 'application/vnd.apple.mpegurl'})});
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-fetch the m3u8, filter unknown directives, then parse from a Blob
const resp = await fetch(url);
const text = await resp.text();
const KNOWN = new Set([
  '#EXTM3U', '#EXT-X-VERSION', '#EXT-X-INDEPENDENT-SEGMENTS', '#EXT-X-MEDIA',
  '#EXT-X-TARGETDURATION', '#EXTINF', '#EXT-X-ENDLIST', '#EXT-X-PLAYLIST-TYPE',
  '#EXT-X-MEDIA-SEQUENCE', '#EXT-X-DISCONTINUITY-SEQUENCE', '#EXT-X-STREAM-INF',
  '#EXT-X-I-FRAME-STREAM-INF', '#EXT-X-ALLOW-CACHE', '#EXT-X-MAP',
  '#EXT-X-PROGRAM-DATE-TIME',
]);
const filtered = text
  .split('\n')
  .filter((line) => {
    const t = line.trim();
    if (!t.startsWith('#')) return true;
    const directive = t.split(':')[0];
    return KNOWN.has(directive);
  })
  .join('\n');
await parseMedia({src: new Blob([filtered], {type: 'application/vnd.apple.mpegurl'})});

Try / catch

try {
  await parseMedia({src: url});
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Unknown directive')) {
    // filter unsupported directives from the m3u8 and retry, or reject
  }
  throw e;
}

Prevention

When it happens

Trigger: Any HLS directive not in the parser's recognized list, including: #EXT-X-KEY (encryption), #EXT-X-DISCONTINUITY (without -SEQUENCE suffix), #EXT-X-BYTERANGE, #EXT-X-SESSION-DATA, #EXT-X-START, #EXT-X-I-FRAMES-ONLY, #EXT-X-DATERANGE, #EXT-X-VERSION newer directives, or comment lines starting with '#'.

Common situations: HLS playlists with DRM/encryption (#EXT-X-KEY); playlists using byte-range addressing (#EXT-X-BYTERANGE); playlists with discontinuity markers; newer-spec or vendor-extension directives; any playlist using a feature this parser doesn't yet support.

Related errors


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