{"record":{"id":"d403c5efe8e26e88","repo":"remotion-dev/remotion","slug":"value-is-null","errorCode":null,"errorMessage":"Value is null","messagePattern":"Value is null","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/media-parser/src/containers/m3u/parse-m3u-media-directive.ts","lineNumber":13,"sourceCode":"import {splitRespectingQuotes} from './parse-stream-inf';\nimport type {M3uMediaInfo} from './types';\n\nexport const parseM3uKeyValue = (str: string) => {\n\tconst quotes = splitRespectingQuotes(str);\n\tconst map: Record<string, string> = {};\n\tfor (const quote of quotes) {\n\t\tconst firstColon = quote.indexOf('=');\n\t\tconst key =\n\t\t\tfirstColon === -1 ? quote : (quote.slice(0, firstColon) as string);\n\t\tconst value = firstColon === -1 ? null : quote.slice(firstColon + 1);\n\t\tif (value === null) {\n\t\t\tthrow new Error('Value is null');\n\t\t}\n\n\t\tconst actualValue =\n\t\t\tvalue?.startsWith('\"') && value?.endsWith('\"')\n\t\t\t\t? value.slice(1, -1)\n\t\t\t\t: value;\n\n\t\tmap[key] = actualValue;\n\t}\n\n\treturn map;\n};\n\nexport const parseM3uMediaDirective = (str: string): M3uMediaInfo => {\n\tconst map = parseM3uKeyValue(str);\n\n\treturn {\n\t\ttype: 'm3u-media-info',","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/media-parser/src/containers/m3u/parse-m3u-media-directive.ts#L1-L31","documentation":"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.","triggerScenarios":"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.","commonSituations":"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().","solutions":["Verify all attributes in #EXT-X-MEDIA, #EXT-X-STREAM-INF, and #EXT-X-MAP use KEY=VALUE format with no bare keys","Check for unescaped commas inside quoted attribute values that could create spurious bare tokens","Regenerate the playlist with a compliant HLS packager"],"exampleFix":"// before — bare token 'AUTOSELECT' without a value\n#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aac\",AUTOSELECT,NAME=\"English\"\n\n// after\n#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID=\"aac\",AUTOSELECT=YES,NAME=\"English\"","handlingStrategy":"validation","validationCode":"// Pre-fetch and validate that all attributes in EXT-* directives have KEY=VALUE format\nconst text = await (await fetch(url)).text();\nfor (const line of text.split('\\n')) {\n  const trimmed = line.trim();\n  if (\n    trimmed.startsWith('#EXT-X-MEDIA:') ||\n    trimmed.startsWith('#EXT-X-STREAM-INF:') ||\n    trimmed.startsWith('#EXT-X-MAP:')\n  ) {\n    const attrs = trimmed.slice(trimmed.indexOf(':') + 1);\n    // crude check: every comma-separated token should contain '='\n    for (const token of attrs.split(',')) {\n      if (token.trim() && !token.includes('=')) {\n        throw new Error(`Attribute token without '=': ${token}`);\n      }\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await parseMedia({src: url});\n} catch (e) {\n  if (e instanceof Error && e.message === 'Value is null') {\n    // a directive attribute list contains a bare token without '=' — fix the playlist\n  }\n  throw e;\n}","preventionTips":["Verify all attributes in EXT-X-MEDIA, EXT-X-STREAM-INF, and EXT-X-MAP directives use KEY=VALUE format","Check for unescaped commas inside quoted attribute values that could split tokens incorrectly","Use a compliant packager to avoid malformed attribute lists"],"tags":["hls","m3u8","attribute","malformed","key-value","ext-x-media"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}