sgl-project/sglang · error · Error

Missing previous frame for delta payload

Error message

Missing previous frame for delta payload

What it means

deterministic_all_reduce (ROCm) looks up the input tensor's data pointer in fa->buffers_. When not found and the stream is not graph-capturing, it throws 'buffer not registered!'.

Source

Thrown at python/sglang/multimodal_gen/apps/realtime_webui/decoder_worker.js:32

  if (typeof DecompressionStream === "undefined") {
    throw new Error("This browser does not support gzip stream decoding");
  }
  const stream = new Blob([payload]).stream().pipeThrough(new DecompressionStream("gzip"));
  return new Uint8Array(await new Response(stream).arrayBuffer());
}

async function restoreDeltaGzipFrames(header, payload) {
  const frameBytes = Number(header.bytes_per_frame);
  const count = Number(header.num_frames);
  const expectedSize = frameBytes * count;
  const restored = await gunzipBytes(payload);
  if (restored.length !== expectedSize) {
    throw new Error(`delta payload size mismatch: expected ${expectedSize}, got ${restored.length}`);
  }

  let previous = header.delta_reference === "previous-frame" ? lastFrame : null;
  if (header.delta_reference === "previous-frame") {
    if (!previous) throw new Error("Missing previous frame for delta payload");
    if (previous.byteLength !== frameBytes) {
      throw new Error("Previous frame size does not match current delta payload");
    }
  }

  for (let f = 0; f < count; f++) {
    const offset = f * frameBytes;
    if (previous) {
      for (let i = 0; i < frameBytes; i++) restored[offset + i] ^= previous[i];
    }
    previous = restored.slice(offset, offset + frameBytes);
  }
  lastFrame = previous;
  return restored;
}

function rawFramesToRgbaBuffers(header, payload) {
  const width = Number(header.width);

View on GitHub (pinned to 0132848349)

Solutions

  1. Register the buffer first (register_buffer/ipc exchange) or use deterministic_all_reduce_unreg with a registered staging buffer
  2. Copy input into a previously registered buffer before the call
  3. Run under CUDA graph capture where unregistered buffers are recorded

Example fix

# before
deterministic_all_reduce(fa, new_tensor, out)
# after
deterministic_all_reduce_unreg(fa, new_tensor, registered_staging, out)
Defensive patterns

Strategy: fallback

Validate before calling

if inp.data_ptr() not in fa.buffers_:
    use_unreg = True  # deterministic_all_reduce_unreg with staging buffer

Try / catch

try:
    deterministic_all_reduce(fa, inp, out)
except RuntimeError as e:
    if 'not registered' in str(e):
        deterministic_all_reduce_unreg(fa, inp, staging, out)
    else:
        raise

Prevention

When it happens

Trigger: Calling deterministic_all_reduce with a tensor whose pointer was never registered with the CustomAllreduce object, outside CUDA graph capture.

Common situations: Eager execution with freshly allocated tensors; tensors reallocated by the PyTorch caching allocator so addresses differ from registered ones; skipping register_buffer when wiring up deterministic allreduce.

Related errors


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