sgl-project/sglang · error · ValueError

SANA-WM refiner decoding expects decoded video shaped (B, C,

Error message

SANA-WM refiner decoding expects decoded video shaped (B, C, T, H, W), got {tuple(frames.shape)}.

What it means

The refiner's decode() calls the base VAE decode and verifies the result is a 5D video tensor (B, C, T, H, W). If the VAE returns a 4D image tensor or another rank, decoding cannot proceed with the sink-frame logic, so it raises with the observed shape.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/sana_wm/refiner.py:783

            (getattr(batch, "extra", None) or {}).get("sana_wm_refiner_applied", True)
        )
        try:
            return super().forward(batch, server_args)
        finally:
            self._drop_refiner_sink = True

    @torch.no_grad()
    def decode(
        self,
        latents: torch.Tensor,
        server_args: ServerArgs,
        *,
        vae_dtype: torch.dtype,
    ) -> torch.Tensor:
        frames = super().decode(latents, server_args, vae_dtype=vae_dtype)
        log_sana_wm_tensor_stats("refiner.decode.frames_with_sink", frames)
        if frames.ndim != 5:
            raise ValueError(
                "SANA-WM refiner decoding expects decoded video shaped "
                f"(B, C, T, H, W), got {tuple(frames.shape)}."
            )
        if frames.shape[2] <= 1:
            raise ValueError(
                "SANA-WM refiner decoding expected a sink frame plus refined "
                f"frames, got temporal length {frames.shape[2]}."
            )
        if not getattr(self, "_drop_refiner_sink", True):
            log_sana_wm_tensor_stats("refiner.decode.frames_output", frames)
            return frames
        # Match NVlabs `inference_sana_wm.py`: decode with the clean sink anchor,
        # then drop the first frame from the returned video.
        frames = frames[:, :, 1:].contiguous()
        log_sana_wm_tensor_stats("refiner.decode.frames_output", frames)
        return frames

View on GitHub (pinned to 0132848349)

Solutions

  1. Load the supported causal video VAE for the SANA-WM pipeline
  2. If wrapping the VAE, preserve the 5D video output shape
  3. Verify vae_dtype/component path configuration matches the video model

Example fix

# before
frames = vae.decode(latents)            # returns (B, C, H, W)
# after
frames = vae.decode(latents.squeeze(0)).unsqueeze(0)  # keep (B, C, T, H, W)
# or: load the causal video VAE so decode returns 5D natively
Defensive patterns

Strategy: validation

Validate before calling

frames = super_decode(latents)
if frames.ndim != 5:
    frames = frames.unsqueeze(2) if frames.ndim == 4 else frames

Type guard

def is_5d_video(t) -> bool:
    return isinstance(t, torch.Tensor) and t.ndim == 5

Try / catch

try:
    return stage.decode(latents, server_args, vae_dtype=dt)
except ValueError as e:
    if "(B, C, T, H, W)" in str(e):
        raise TypeError(f"VAE {type(stage.vae).__name__} returns non-video output; load the causal video VAE")
    raise

Prevention

When it happens

Trigger: Loading an image VAE (or a VAE wrapper returning 4D) instead of the causal video VAE; a decode path that squeezes the temporal dimension for single-chunk outputs.

Common situations: Pointing --component_paths.vae at image VAE weights; a custom VAE wrapper normalizing outputs to 4D; config drift after changing pipeline components.

Related errors


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