{"record":{"id":"99921537348622b6","repo":"sgl-project/sglang","slug":"missing-previous-frame-for-delta-payload-999215","errorCode":null,"errorMessage":"Missing previous frame for delta payload","messagePattern":"Missing previous frame for delta payload","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/apps/realtime_webui/decoder_worker.js","lineNumber":32,"sourceCode":"  if (typeof DecompressionStream === \"undefined\") {\n    throw new Error(\"This browser does not support gzip stream decoding\");\n  }\n  const stream = new Blob([payload]).stream().pipeThrough(new DecompressionStream(\"gzip\"));\n  return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\nasync function restoreDeltaGzipFrames(header, payload) {\n  const frameBytes = Number(header.bytes_per_frame);\n  const count = Number(header.num_frames);\n  const expectedSize = frameBytes * count;\n  const restored = await gunzipBytes(payload);\n  if (restored.length !== expectedSize) {\n    throw new Error(`delta payload size mismatch: expected ${expectedSize}, got ${restored.length}`);\n  }\n\n  let previous = header.delta_reference === \"previous-frame\" ? lastFrame : null;\n  if (header.delta_reference === \"previous-frame\") {\n    if (!previous) throw new Error(\"Missing previous frame for delta payload\");\n    if (previous.byteLength !== frameBytes) {\n      throw new Error(\"Previous frame size does not match current delta payload\");\n    }\n  }\n\n  for (let f = 0; f < count; f++) {\n    const offset = f * frameBytes;\n    if (previous) {\n      for (let i = 0; i < frameBytes; i++) restored[offset + i] ^= previous[i];\n    }\n    previous = restored.slice(offset, offset + frameBytes);\n  }\n  lastFrame = previous;\n  return restored;\n}\n\nfunction rawFramesToRgbaBuffers(header, payload) {\n  const width = Number(header.width);","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/apps/realtime_webui/decoder_worker.js#L14-L50","documentation":"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!'.","triggerScenarios":"Calling deterministic_all_reduce with a tensor whose pointer was never registered with the CustomAllreduce object, outside CUDA graph capture.","commonSituations":"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.","solutions":["Register the buffer first (register_buffer/ipc exchange) or use deterministic_all_reduce_unreg with a registered staging buffer","Copy input into a previously registered buffer before the call","Run under CUDA graph capture where unregistered buffers are recorded"],"exampleFix":"# before\ndeterministic_all_reduce(fa, new_tensor, out)\n# after\ndeterministic_all_reduce_unreg(fa, new_tensor, registered_staging, out)","handlingStrategy":"fallback","validationCode":"if inp.data_ptr() not in fa.buffers_:\n    use_unreg = True  # deterministic_all_reduce_unreg with staging buffer","typeGuard":null,"tryCatchPattern":"try:\n    deterministic_all_reduce(fa, inp, out)\nexcept RuntimeError as e:\n    if 'not registered' in str(e):\n        deterministic_all_reduce_unreg(fa, inp, staging, out)\n    else:\n        raise","preventionTips":["Pre-register persistent buffers","Keep a registered staging buffer for ad-hoc tensors"],"tags":["rocm","allreduce","deterministic","buffer-registration"],"backgroundTag":"buffer-not-registered","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}