sgl-project/sglang · error · ValueError

SANA-WM realtime denoising expects this tick's pre-noised ch

Error message

SANA-WM realtime denoising expects this tick's pre-noised chunk latents (B, C, n, H, W) from the latent-preparation stage.

What it means

_forward_realtime_chunk requires batch.latents to be a 5D (B, C, n, H, W) tensor of pre-noised chunk latents produced by the latent-preparation stage of the realtime streaming pipeline. None or wrong rank means the realtime tick's input is missing/malformed.

Source

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

        )

    @staticmethod
    def _evict_stale_kv_cache(
        kv_cache: list,
        chunk_idx: int,
        valid: list[int],
        num_cached_blocks: int,
        num_blocks: int,
    ) -> None:
        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

View on GitHub (pinned to 0132848349)

Solutions

  1. Confirm the latent-preparation stage runs before the streaming denoiser for every tick
  2. Validate batch.latents is not None and ndim==5 at the tick boundary before dispatch
  3. Re-run the tick after a session restart so latents are re-prepared

Example fix

# before
resp = streaming_stage.forward(tick_batch, server_args)  # latents None
# after
tick_batch = latent_prep_stage.forward(tick_batch, server_args)  # sets 5D latents
resp = streaming_stage.forward(tick_batch, server_args)
Defensive patterns

Strategy: validation

Validate before calling

if batch.latents is None or batch.latents.ndim != 5:
    batch = latent_prep_stage.forward(batch, server_args)
assert batch.latents is not None and batch.latents.ndim == 5

Type guard

def has_realtime_chunk_latents(b) -> bool:
    return b.latents is not None and b.latents.ndim == 5

Try / catch

try:
    resp = stage.forward(batch, server_args)
except ValueError as e:
    if "pre-noised chunk latents" in str(e):
        batch = latent_prep_stage.forward(batch, server_args)
        resp = stage.forward(batch, server_args)
    else:
        raise

Prevention

When it happens

Trigger: Dispatching a realtime session chunk before the latent-preparation stage ran, or that stage failing silently; feeding offline-style 4D latents into the realtime path; batch.latents dropped during Req serialization for the session tick.

Common situations: Wiring the streaming denoiser directly after conditioning without the latent-prep stage; a session-restart race where chunk 0 arrives without fresh latents; a preprocessing bug squeezing the chunk dim.

Related errors


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