invoke-ai/InvokeAI · error · ValueError

Latent channel mismatch: these latents have {latents.shape[1

Error message

Latent channel mismatch: these latents have {latents.shape[1]} channels but the selected VAE expects {vae_info.model.config.z_dim}. A14B models need the 16-channel Wan 2.1 VAE; TI2V-5B needs the 48-channel Wan 2.2 VAE.

What it means

After confirming the VAE is an AutoencoderKLWan, invoke() checks that latents.shape[1] equals the VAE's config.z_dim. Wan 2.1 A14B latents are 16-channel and Wan 2.2 TI2V-5B latents are 48-channel; decoding through a mismatched VAE would corrupt output, so a ValueError is raised. This mirrors the equivalent check in wan_latents_to_image.

Source

Thrown at invokeai/app/invocations/wan_latents_to_video.py:110

        latents = context.tensors.load(self.latents.latents_name)
        _validate_video_latent_batch(latents)
        if latents.ndim == 4:
            # Promote 4D (single-frame) to 5D so this node can also serve as a
            # one-frame "video" encode if someone wires it that way.
            latents = latents.unsqueeze(2)
        if latents.ndim != 5:
            raise ValueError(
                f"Wan latents-to-video expects a 5D latent tensor [B, C, T, H, W]; got {tuple(latents.shape)}."
            )
        if any(size == 0 for size in latents.shape[2:]):
            raise ValueError("Wan latents-to-video requires non-empty temporal and spatial dimensions.")

        vae_info = context.models.load(self.vae.vae)
        if not isinstance(vae_info.model, AutoencoderKLWan):
            raise TypeError(f"Expected AutoencoderKLWan for Wan VAE, got {type(vae_info.model).__name__}.")

        if latents.shape[1] != vae_info.model.config.z_dim:
            raise ValueError(
                f"Latent channel mismatch: these latents have {latents.shape[1]} channels but the "
                f"selected VAE expects {vae_info.model.config.z_dim}. A14B models need the 16-channel Wan 2.1 VAE; "
                "TI2V-5B needs the 48-channel Wan 2.2 VAE."
            )

        _, _, t_lat, h_lat, w_lat = latents.shape
        spatial_scale = getattr(vae_info.model.config, "scale_factor_spatial", None) or 8
        temporal_scale = getattr(vae_info.model.config, "scale_factor_temporal", None) or 4
        t_pixel = (t_lat - 1) * temporal_scale + 1
        h_pixel, w_pixel = h_lat * spatial_scale, w_lat * spatial_scale
        optimize_memory = context.config.get().wan_memory_optimization

        estimated_working_memory = estimate_vae_working_memory_wan(
            operation="decode",
            vae=vae_info.model,
            pixel_height=h_pixel,
            pixel_width=w_pixel,
            pixel_frames=t_pixel,

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Use the VAE matching the latents: 16-channel Wan 2.1 VAE for A14B, 48-channel Wan 2.2 VAE for TI2V-5B.
  2. Verify latents.shape[1] against vae.config.z_dim before invoking.
  3. Regenerate latents with a denoiser matching the chosen VAE's latent space.
  4. Fix workflow templates that reference the wrong VAE for the selected model.

Example fix

// before
latents = wan22_5b_denoiser_output  # 48 channels
vae = load_vae("wan2.1-vae")  # z_dim = 16
video = wan_latents_to_video(latents=latents, vae=vae)  # ValueError
// after
assert latents.shape[1] == vae_config.z_dim
video = wan_latents_to_video(latents=latents, vae=wan22_vae)
Defensive patterns

Strategy: validation

Validate before calling

z_dim = vae_info.model.config.z_dim
if latents.shape[1] != z_dim:
    raise ValueError(f"latents ch={latents.shape[1]} vs VAE z_dim={z_dim}; match 16ch<->Wan2.1, 48ch<->Wan2.2")

Type guard

def latents_match_vae(latents, vae) -> bool:
    return latents.ndim == 5 and latents.shape[1] == vae.config.z_dim

Try / catch

try:
    video = node.invoke(context)
except ValueError as e:
    if "Latent channel mismatch" in str(e):
        vae = load_vae_with_z_dim(latents.shape[1])
        video = replace(node, vae=vae).invoke(context)
    else:
        raise

Prevention

When it happens

Trigger: Calling wan_latents_to_video.invoke() with latents whose channel count differs from the loaded Wan VAE's z_dim — e.g. 16-channel Wan 2.1 latents sent to the 48-channel TI2V-5B VAE or the reverse.

Common situations: Mixing Wan 2.1 and Wan 2.2 components in one workflow; switching transformer checkpoints without swapping the VAE node; stale workflow files after a model upgrade.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/92b32b707081023b. Report an issue: GitHub.