sgl-project/sglang · error · ValueError

SANA-WM realtime denoising requires a realtime session

Error message

SANA-WM realtime denoising requires a realtime session

What it means

The realtime per-chunk path stores autoregressive state (latents, scheduler, KV cache) in a per-session RealtimeCausalDiTState. If batch.session is None there is no session to key the state on, so realtime denoising cannot proceed.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/sana_wm/streaming.py:257

        SanaWMSelfForcingSampler.evict_stale_kv_cache(
            kv_cache, chunk_idx, valid, num_cached_blocks, num_blocks
        )

    # Realtime per-chunk path (sessions): per-session state in RealtimeCausalDiTState.
    @torch.no_grad()
    def _forward_realtime_chunk(self, batch: Req, server_args: ServerArgs) -> Req:
        if batch.latents is None or batch.latents.ndim != 5:
            raise ValueError(
                "SANA-WM realtime denoising expects this tick's pre-noised chunk "
                "latents (B, C, n, H, W) from the latent-preparation stage."
            )
        pcfg = server_args.pipeline_config
        device = get_local_torch_device()
        target_dtype = PRECISION_TO_TYPE.get(
            getattr(pcfg, "dit_precision", "bf16"), torch.bfloat16
        )
        if batch.session is None:
            raise ValueError("SANA-WM realtime denoising requires a realtime session")
        state = get_realtime_causal_dit_state(batch.session)
        if batch.block_idx == 0 and state.latents is not None:
            state.dispose()  # session restart on chunk 0 (mirrors the base stage)

        sc = self._resolve_stream_conditioning(
            batch, server_args, device=device, target_dtype=target_dtype
        )
        sampler_cfg = sc.sampler_cfg
        incoming = batch.latents.to(device=device, dtype=target_dtype).clone()
        plan = list(batch.extra.get("sana_wm_chunk_plan") or [incoming.shape[2]])
        if sum(plan) != incoming.shape[2]:
            raise ValueError(
                f"chunk plan {plan} does not cover the incoming {incoming.shape[2]} frames"
            )
        if state.scheduler is None:
            state.scheduler = FlowMatchEulerDiscreteScheduler(shift=1.0)
        kv_cache = state.kv_cache
        if kv_cache is None:

View on GitHub (pinned to 0132848349)

Solutions

  1. Create the realtime session before sending chunks and attach it to each tick's Req
  2. Fix request routing so only session-backed Reqs take the realtime path
  3. If the session was disposed, re-establish it and resend from chunk 0

Example fix

# before
batch.session = None
streaming_stage.forward(batch, server_args)
# after
batch.session = get_or_create_session(session_id)
streaming_stage.forward(batch, server_args)
Defensive patterns

Strategy: validation

Validate before calling

if batch.session is None:
    batch.session = get_or_create_session(session_id)

Type guard

null

Try / catch

try:
    resp = stage.forward(batch, server_args)
except ValueError as e:
    if "realtime session" in str(e):
        raise SessionLost(session_id) from e
    raise

Prevention

When it happens

Trigger: Sending a realtime chunk through the streaming stage with batch.session unset — e.g. an offline-style Req routed into the realtime path, or a session that was closed/never created before the first tick.

Common situations: Misrouted requests (offline vs realtime dispatch based on session presence); a gateway/proxy stripping the session field; racing session teardown with in-flight chunks.

Related errors


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