{"record":{"id":"92b32b707081023b","repo":"invoke-ai/InvokeAI","slug":"latent-channel-mismatch-these-latents-have-laten-92b32b","errorCode":null,"errorMessage":"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.","messagePattern":"Latent channel mismatch: these latents have (.+?) channels but the selected VAE expects (.+?)\\. A14B models need the 16-channel Wan 2\\.1 VAE; TI2V-5B needs the 48-channel Wan 2\\.2 VAE\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/wan_latents_to_video.py","lineNumber":110,"sourceCode":"        latents = context.tensors.load(self.latents.latents_name)\n        _validate_video_latent_batch(latents)\n        if latents.ndim == 4:\n            # Promote 4D (single-frame) to 5D so this node can also serve as a\n            # one-frame \"video\" encode if someone wires it that way.\n            latents = latents.unsqueeze(2)\n        if latents.ndim != 5:\n            raise ValueError(\n                f\"Wan latents-to-video expects a 5D latent tensor [B, C, T, H, W]; got {tuple(latents.shape)}.\"\n            )\n        if any(size == 0 for size in latents.shape[2:]):\n            raise ValueError(\"Wan latents-to-video requires non-empty temporal and spatial dimensions.\")\n\n        vae_info = context.models.load(self.vae.vae)\n        if not isinstance(vae_info.model, AutoencoderKLWan):\n            raise TypeError(f\"Expected AutoencoderKLWan for Wan VAE, got {type(vae_info.model).__name__}.\")\n\n        if latents.shape[1] != vae_info.model.config.z_dim:\n            raise ValueError(\n                f\"Latent channel mismatch: these latents have {latents.shape[1]} channels but the \"\n                f\"selected VAE expects {vae_info.model.config.z_dim}. A14B models need the 16-channel Wan 2.1 VAE; \"\n                \"TI2V-5B needs the 48-channel Wan 2.2 VAE.\"\n            )\n\n        _, _, t_lat, h_lat, w_lat = latents.shape\n        spatial_scale = getattr(vae_info.model.config, \"scale_factor_spatial\", None) or 8\n        temporal_scale = getattr(vae_info.model.config, \"scale_factor_temporal\", None) or 4\n        t_pixel = (t_lat - 1) * temporal_scale + 1\n        h_pixel, w_pixel = h_lat * spatial_scale, w_lat * spatial_scale\n        optimize_memory = context.config.get().wan_memory_optimization\n\n        estimated_working_memory = estimate_vae_working_memory_wan(\n            operation=\"decode\",\n            vae=vae_info.model,\n            pixel_height=h_pixel,\n            pixel_width=w_pixel,\n            pixel_frames=t_pixel,","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/wan_latents_to_video.py#L92-L128","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use the VAE matching the latents: 16-channel Wan 2.1 VAE for A14B, 48-channel Wan 2.2 VAE for TI2V-5B.","Verify latents.shape[1] against vae.config.z_dim before invoking.","Regenerate latents with a denoiser matching the chosen VAE's latent space.","Fix workflow templates that reference the wrong VAE for the selected model."],"exampleFix":"// before\nlatents = wan22_5b_denoiser_output  # 48 channels\nvae = load_vae(\"wan2.1-vae\")  # z_dim = 16\nvideo = wan_latents_to_video(latents=latents, vae=vae)  # ValueError\n// after\nassert latents.shape[1] == vae_config.z_dim\nvideo = wan_latents_to_video(latents=latents, vae=wan22_vae)","handlingStrategy":"validation","validationCode":"z_dim = vae_info.model.config.z_dim\nif latents.shape[1] != z_dim:\n    raise ValueError(f\"latents ch={latents.shape[1]} vs VAE z_dim={z_dim}; match 16ch<->Wan2.1, 48ch<->Wan2.2\")","typeGuard":"def latents_match_vae(latents, vae) -> bool:\n    return latents.ndim == 5 and latents.shape[1] == vae.config.z_dim","tryCatchPattern":"try:\n    video = node.invoke(context)\nexcept ValueError as e:\n    if \"Latent channel mismatch\" in str(e):\n        vae = load_vae_with_z_dim(latents.shape[1])\n        video = replace(node, vae=vae).invoke(context)\n    else:\n        raise","preventionTips":["Pair each transformer checkpoint with its matching VAE node.","Assert channel count == z_dim before invoke.","Avoid mixing Wan 2.1 and 2.2 components in one graph.","Regenerate latents if you switch VAE lineage."],"tags":["wan","vae","shape-mismatch","latent-channels"],"backgroundTag":"latent-channel-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}