sgl-project/sglang · error · Error

H.264 encoder did not return MP4 decoder config

Error message

H.264 encoder did not return MP4 decoder config

What it means

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'.

Source

Thrown at python/sglang/multimodal_gen/apps/realtime_webui/app.js:709

    duration: chunk.duration || 0,
    key: chunk.type === "key",
  });
}

function downloadBlob(blob, fileName) {
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = fileName;
  document.body.appendChild(link);
  link.click();
  link.remove();
  window.setTimeout(() => URL.revokeObjectURL(url), 1000);
}

function buildRecordingMp4() {
  if (!recordingEncoderConfig.description) {
    throw new Error("H.264 encoder did not return MP4 decoder config");
  }
  const width = recordingEncoderConfig.width;
  const height = recordingEncoderConfig.height;
  const samples = normalizeRecordingSamples(recordingSamples);
  const mdatPayload = concatBytes(samples.map((sample) => sample.data));
  const ftyp = mp4Box("ftyp", ascii("isom"), u32(0x200), ascii("isom"), ascii("iso2"), ascii("avc1"), ascii("mp41"));
  const mdat = mp4Box("mdat", mdatPayload);
  const firstSampleOffset = ftyp.byteLength + 8;
  const moov = buildMoovBox({
    width,
    height,
    samples,
    firstSampleOffset,
    avcConfig: new Uint8Array(recordingEncoderConfig.description),
  });
  return new Blob([ftyp, mdat, moov], { type: "video/mp4" });
}

View on GitHub (pinned to 0132848349)

Solutions

  1. Write the range as 'L-R|config' with a single ASCII hyphen, e.g. '2-4|8'
  2. Check for stray '-' characters inside numbers (e.g. '-2--4') that split into 3+ tokens
  3. Add a Python-side regex pre-check like ^\d+-\d+\|\d+( \d+-\d+\|\d+)*$ before calling into C++

Example fix

# before
param.resetBatchReturnTokenNum("2:4|8")

# after
param.resetBatchReturnTokenNum("2-4|8")
Defensive patterns

Strategy: validation

Validate before calling

assert all(re.fullmatch(r"\d+-\d+\|\d+", s) for s in cfg.split()), "each range must be L-R with one hyphen"

Type guard

def has_wellformed_ranges(cfg: str) -> bool:
    return all(len(s.split("|")[0].split("-")) == 2 for s in cfg.split())

Try / catch

try:
    param.resetBatchReturnTokenNum(cfg)
except RuntimeError as e:
    if "failed to get range" in str(e):
        raise ValueError(f"range part malformed in {cfg!r}; use 'L-R|value'") from e
    raise

Prevention

When it happens

Trigger: 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.

Common situations: Using ':' or '..' instead of '-' in range specs, negative or malformed numbers producing extra '-' splits, or hand-edited config strings with a mistyped separator.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/a612adf87b371e99. Report an issue: GitHub.