sgl-project/sglang · error · Error
Missing previous frame for delta payload
Error message
Missing previous frame for delta payload
What it means
SuffixAutomaton::appendTokens refuses to add tokens once finalize() has been called (finalized_ flag). A finalized SAM is a read-only query structure for longest-match lookups, so appending would invalidate its internal indexes.
Source
Thrown at python/sglang/multimodal_gen/apps/realtime_webui/app.js:1079
async function gunzipBytes(payload) {
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 restoreDeltaGzipRawRgb(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" ? lastRawRgbFrame : null;
if (header.delta_reference === "previous-frame" && !previous) {
throw new Error("Missing previous frame for delta payload");
}
for (let f = 0; f < count; f++) {
const current = f * frameBytes;
if (previous) {
for (let i = 0; i < frameBytes; i++) {
restored[current + i] ^= previous[i];
}
}
previous = restored.slice(current, current + frameBytes);
}
return restored;
}
async function framePayloadToImageData(header, payload) {
let rawPayload;
const isRgba = header.content_type === RAW_RGBA_DELTA_GZIP_CONTENT_TYPE;
if (
header.content_type === WEBP_FRAME_CONTENT_TYPE ||View on GitHub (pinned to 0132848349)
Solutions
- Call reset()/re-create the SAM before appending new tokens after a finalize
- Restructure so all appendTokens calls happen before the single finalize() call
- Audit early-finalize paths (exceptions, early returns) if you believe the SAM shouldn't be finalized yet
Example fix
// before sam.appendTokens(prompt1); sam.finalize(); sam.appendTokens(prompt2); // throws // after sam.appendTokens(prompt1); sam.finalize(); // ... matching on prompt1 ... sam.reset(); sam.appendTokens(prompt2); sam.finalize();
Defensive patterns
Strategy: validation
Validate before calling
if sam.finalized: # or track finalize() calls yourself
sam.reset()
sam.appendTokens(tokens) Type guard
def can_append(sam) -> bool:
return not getattr(sam, "finalized_", False) and not getattr(sam, "is_finalized", lambda: False)() Try / catch
try:
sam.appendTokens(tokens)
except RuntimeError as e:
if "after finalizing" in str(e):
sam.reset(); sam.appendTokens(tokens)
else:
raise Prevention
- One SAM per request/generation, or reset() between reuses
- Keep a Python-side finalized flag mirroring the C++ state
- Ensure finalize() is the last step of the build phase, after all appends
When it happens
Trigger: Calling appendTokens() on a SuffixAutomaton after finalize() was invoked — e.g. trying to stream more prompt tokens into a SAM already finalized for matching, or reusing a SAM object across requests without reset.
Common situations: Reusing a per-request suffix automaton across generations without resetting, incremental corpus updates after the matcher was built, or control-flow bugs where finalize() runs early (e.g. in an error path) before the final appendTokens.
Related errors
- appendExternalCorpusTokens called without startExternalCorpu
- finishExternalCorpusLoad called without startExternalCorpusL
- startExternalCorpusLoad called while another load is in prog
- No frames were recorded
- This browser cannot encode H.264 MP4
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/589dcafc302475a3.
Report an issue: GitHub.