sgl-project/sglang · error · Error

No frames were recorded

Error message

No frames were recorded

What it means

Thrown by the ngram_corpus JIT FFI write_result_ helper when the caller-provided out_mask tensor's first dimension is smaller than the mask vector produced by the matcher. The C++ side memcpy's result.mask into the pre-allocated output buffer, so it defensively checks capacity first and refuses to overflow the tensor.

Source

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

    recordingTimer = 0;
  }
  recordingSaving = true;
  updateRecordButton();

  let fileHandle = null;
  const fileName = recordingFileName();
  try {
    if (window.showSaveFilePicker) {
      fileHandle = await window.showSaveFilePicker({
        suggestedName: fileName,
        types: [{
          description: "MP4 video",
          accept: { "video/mp4": [".mp4"] },
        }],
      });
    }
    await recordingEncodeChain;
    if (!recordingEncoder || !recordingSamples.length) throw new Error("No frames were recorded");
    await recordingEncoder.flush();
    const mp4Blob = buildRecordingMp4();
    if (fileHandle) {
      const writable = await fileHandle.createWritable();
      await writable.write(mp4Blob);
      await writable.close();
    } else {
      downloadBlob(mp4Blob, fileName);
    }
    addHistory(`saved ${recordingSamples.length} frames as mp4`);
  } catch (error) {
    if (error?.name === "AbortError") {
      addHistory("recording save canceled");
    } else {
      addHistory(error.message || "recording save failed");
      setStatus("Save failed", "error");
    }
  } finally {

View on GitHub (pinned to 0132848349)

Solutions

  1. Check the FFI contract: out_mask must have size(0) >= result.mask.size(); allocate it with the exact expected mask length returned/agreed by batch_match_stateful before the call
  2. If the kernel reports the required size (or a paired output-size FFI), query it first and allocate outputs from that value instead of estimating
  3. Rebuild/reinstall the JIT extension (python -m sglang.kernels.jit build or equivalent) so Python bindings and C++ sources are from the same commit
  4. Report upstream if the mask length is genuinely nondeterministic relative to the documented output shape

Example fix

// before
out_mask = torch.empty(old_batch_size, dtype=torch.uint8, device="cuda")
ffi.batch_match_stateful(state, tokens, out_tokens, out_mask)

// after
out_mask = torch.empty(expected_mask_len, dtype=torch.uint8, device="cuda")
assert out_mask.size(0) >= ffi.required_mask_size(state)
ffi.batch_match_stateful(state, tokens, out_tokens, out_mask)
Defensive patterns

Strategy: validation

Validate before calling

expected = ffi.mask_output_size(state, tokens)  # or the documented fixed relation
if out_mask.size(0) < expected:
    out_mask = torch.empty(expected, dtype=torch.uint8, device=out_mask.device)
# only then call batch_match_stateful

Try / catch

try:
    ffi.batch_match_stateful(...)
except RuntimeError as e:
    if "out_mask buffer too small" in str(e):
        raise ValueError(f"out_mask must have >= matcher mask size; got {out_mask.size(0)}") from e
    raise

Prevention

When it happens

Trigger: Calling batch_match_stateful (the stateful n-gram batch match FFI entry) with an out_mask tensor whose size(0) is smaller than the number of mask entries the kernel produced for the matched batch — e.g. allocating outputs from a stale/estimated batch size instead of the actual match result size, while out_tokens happens to be large enough.

Common situations: Reusing output buffers sized for a previous smaller batch, computing out_mask's shape from a different quantity (tokens vs mask length) than the kernel writes, or a Python-side size calculation drifting out of sync with the C++ matcher after a version bump of the JIT kernel.

Related errors


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