{"record":{"id":"a612adf87b371e99","repo":"sgl-project/sglang","slug":"h-264-encoder-did-not-return-mp4-decoder-config","errorCode":null,"errorMessage":"H.264 encoder did not return MP4 decoder config","messagePattern":"H\\.264 encoder did not return MP4 decoder config","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/apps/realtime_webui/app.js","lineNumber":709,"sourceCode":"    duration: chunk.duration || 0,\n    key: chunk.type === \"key\",\n  });\n}\n\nfunction downloadBlob(blob, fileName) {\n  const url = URL.createObjectURL(blob);\n  const link = document.createElement(\"a\");\n  link.href = url;\n  link.download = fileName;\n  document.body.appendChild(link);\n  link.click();\n  link.remove();\n  window.setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n\nfunction buildRecordingMp4() {\n  if (!recordingEncoderConfig.description) {\n    throw new Error(\"H.264 encoder did not return MP4 decoder config\");\n  }\n  const width = recordingEncoderConfig.width;\n  const height = recordingEncoderConfig.height;\n  const samples = normalizeRecordingSamples(recordingSamples);\n  const mdatPayload = concatBytes(samples.map((sample) => sample.data));\n  const ftyp = mp4Box(\"ftyp\", ascii(\"isom\"), u32(0x200), ascii(\"isom\"), ascii(\"iso2\"), ascii(\"avc1\"), ascii(\"mp41\"));\n  const mdat = mp4Box(\"mdat\", mdatPayload);\n  const firstSampleOffset = ftyp.byteLength + 8;\n  const moov = buildMoovBox({\n    width,\n    height,\n    samples,\n    firstSampleOffset,\n    avcConfig: new Uint8Array(recordingEncoderConfig.description),\n  });\n  return new Blob([ftyp, mdat, moov], { type: \"video/mp4\" });\n}\n","sourceCodeStart":691,"sourceCodeEnd":727,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/apps/realtime_webui/app.js#L691-L727","documentation":"Thrown by ngram_corpus Param::parse when the left side of a config segment (before '|') does not split on '-' into exactly two tokens. The parser expects a positional range written as 'L-R', e.g. '2-4'.","triggerScenarios":"resetBatchReturnTokenNum receives a segment like '2|8' (range uses wrong separator), '2-4-6' (three range tokens), or '24|8' (missing dash), so splitting part[0] on '-' yields a vector whose size != 2.","commonSituations":"Using ':' or '..' instead of '-' in range specs, negative or malformed numbers producing extra '-' splits, or hand-edited config strings with a mistyped separator.","solutions":["Write the range as 'L-R|config' with a single ASCII hyphen, e.g. '2-4|8'","Check for stray '-' characters inside numbers (e.g. '-2--4') that split into 3+ tokens","Add a Python-side regex pre-check like ^\\d+-\\d+\\|\\d+( \\d+-\\d+\\|\\d+)*$ before calling into C++"],"exampleFix":"# before\nparam.resetBatchReturnTokenNum(\"2:4|8\")\n\n# after\nparam.resetBatchReturnTokenNum(\"2-4|8\")","handlingStrategy":"validation","validationCode":"assert all(re.fullmatch(r\"\\d+-\\d+\\|\\d+\", s) for s in cfg.split()), \"each range must be L-R with one hyphen\"","typeGuard":"def has_wellformed_ranges(cfg: str) -> bool:\n    return all(len(s.split(\"|\")[0].split(\"-\")) == 2 for s in cfg.split())","tryCatchPattern":"try:\n    param.resetBatchReturnTokenNum(cfg)\nexcept RuntimeError as e:\n    if \"failed to get range\" in str(e):\n        raise ValueError(f\"range part malformed in {cfg!r}; use 'L-R|value'\") from e\n    raise","preventionTips":["Always use a single ASCII hyphen in ranges","Avoid negative numbers or stray dashes in the config","Generate configs programmatically instead of hand-editing"],"tags":["ngram","config","parsing","range-validation"],"backgroundTag":"config-string-validation-failed","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}