sgl-project/sglang · error · TypeError

Unsupported VAE encode output for SANA-WM first-frame condit

Error message

Unsupported VAE encode output for SANA-WM first-frame conditioning: {type(encoded).__name__}

What it means

Raised by _extract_vae_latents when the VAE encode() output is neither an object with a latent_dist/sample-able attribute, a non-empty tuple, nor a torch.Tensor — i.e. the VAE returned an unexpected type.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/sana_wm/base.py:1149

    def _extract_vae_latents(encoded: Any) -> torch.Tensor:
        """Return deterministic VAE latents from common Diffusers outputs."""
        latent_dist = getattr(encoded, "latent_dist", None)
        if latent_dist is not None:
            if hasattr(latent_dist, "mode"):
                return latent_dist.mode()
            mean = getattr(latent_dist, "mean", None)
            if isinstance(mean, torch.Tensor):
                return mean
            if callable(mean):
                return mean()
            if hasattr(latent_dist, "sample"):
                return latent_dist.sample()

        if isinstance(encoded, tuple) and encoded:
            return SanaWMBeforeDenoisingStage._extract_vae_latents(encoded[0])
        if isinstance(encoded, torch.Tensor):
            return encoded
        raise TypeError(
            "Unsupported VAE encode output for SANA-WM first-frame conditioning: "
            f"{type(encoded).__name__}"
        )

    def _prepare_noise_latents(
        self,
        shape: tuple,
        dtype: torch.dtype,
        device: torch.device,
        generator: (
            torch.Generator | list[torch.Generator] | tuple[torch.Generator, ...]
        ),
    ) -> torch.Tensor:
        if isinstance(generator, (list, tuple)):
            if not generator:
                raise ValueError("SANA-WM generator list must not be empty.")
            if len(generator) == 1:
                return randn_tensor(

View on GitHub (pinned to 0132848349)

Solutions

  1. Make the custom VAE return a tensor or a tuple whose first element holds latents
  2. Unwrap the latents before returning from a wrapper encode()
  3. Pin/align the diffusers VAE API version the stage expects

Example fix

# before
def encode(self, z): return {'latents': lat}
# after
def encode(self, z): return (lat,)  # tuple; first element extracted
Defensive patterns

Strategy: type-guard

Validate before calling

out = vae.encode(x)
assert isinstance(out, (torch.Tensor, tuple)) or hasattr(out, 'latent_dist')

Type guard

def vae_output_usable(encoded) -> bool:
    return isinstance(encoded, torch.Tensor) or (isinstance(encoded, tuple) and encoded) or hasattr(encoded, 'latent_dist')

Prevention

When it happens

Trigger: Swapping in a custom/different VAE whose encode returns e.g. a dict, a list, or None; VAE version mismatch changing the return type. Called via _vae_encode_image / _encode_first_frame.

Common situations: Upgrading diffusers and the return wrapper changed; using a custom VAE wrapper; monkeypatched VAE in tests returning a plain object.

Related errors


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