remotion-dev/remotion · error · Error

Value is null

Error message

Value is null

What it means

Thrown by parseM3uKeyValue() at parse-m3u-media-directive.ts:13 when processing attribute lists for directives like #EXT-X-MEDIA, #EXT-X-STREAM-INF, and #EXT-X-MAP. Each attribute token is split on the first '=' sign; if a token has no '=' (firstColon === -1), the value is null and the parser throws. HLS attribute lists require all entries to be KEY=VALUE pairs.

Source

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

import {splitRespectingQuotes} from './parse-stream-inf';
import type {M3uMediaInfo} from './types';

export const parseM3uKeyValue = (str: string) => {
	const quotes = splitRespectingQuotes(str);
	const map: Record<string, string> = {};
	for (const quote of quotes) {
		const firstColon = quote.indexOf('=');
		const key =
			firstColon === -1 ? quote : (quote.slice(0, firstColon) as string);
		const value = firstColon === -1 ? null : quote.slice(firstColon + 1);
		if (value === null) {
			throw new Error('Value is null');
		}

		const actualValue =
			value?.startsWith('"') && value?.endsWith('"')
				? value.slice(1, -1)
				: value;

		map[key] = actualValue;
	}

	return map;
};

export const parseM3uMediaDirective = (str: string): M3uMediaInfo => {
	const map = parseM3uKeyValue(str);

	return {
		type: 'm3u-media-info',

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Verify all attributes in #EXT-X-MEDIA, #EXT-X-STREAM-INF, and #EXT-X-MAP use KEY=VALUE format with no bare keys
  2. Check for unescaped commas inside quoted attribute values that could create spurious bare tokens
  3. Regenerate the playlist with a compliant HLS packager

Example fix

// before — bare token 'AUTOSELECT' without a value
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aac",AUTOSELECT,NAME="English"

// after
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aac",AUTOSELECT=YES,NAME="English"
Defensive patterns

Strategy: validation

Validate before calling

// Pre-fetch and validate that all attributes in EXT-* directives have KEY=VALUE format
const text = await (await fetch(url)).text();
for (const line of text.split('\n')) {
  const trimmed = line.trim();
  if (
    trimmed.startsWith('#EXT-X-MEDIA:') ||
    trimmed.startsWith('#EXT-X-STREAM-INF:') ||
    trimmed.startsWith('#EXT-X-MAP:')
  ) {
    const attrs = trimmed.slice(trimmed.indexOf(':') + 1);
    // crude check: every comma-separated token should contain '='
    for (const token of attrs.split(',')) {
      if (token.trim() && !token.includes('=')) {
        throw new Error(`Attribute token without '=': ${token}`);
      }
    }
  }
}

Try / catch

try {
  await parseMedia({src: url});
} catch (e) {
  if (e instanceof Error && e.message === 'Value is null') {
    // a directive attribute list contains a bare token without '=' — fix the playlist
  }
  throw e;
}

Prevention

When it happens

Trigger: An attribute directive containing a bare token without an '=' sign — e.g. #EXT-X-MEDIA:TYPE=AUDIO,NOEQUALS,NAME="English" where 'NOEQUALS' lacks a '=value' suffix. Also fired by malformed comma-splitting where a value containing an unescaped comma creates a bare token.

Common situations: Malformed attribute list from a buggy encoder or packager; typo in a hand-edited playlist (missing '=value'); attribute value containing unescaped commas that confuse the quote-respecting splitter in splitRespectingQuotes().

Related errors


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