{"record":{"id":"699013383a95e378","repo":"invoke-ai/InvokeAI","slug":"wan-latents-to-video-expects-a-5d-latent-tensor-b","errorCode":null,"errorMessage":"Wan latents-to-video expects a 5D latent tensor [B, C, T, H, W]; got {tuple(latents.shape)}.","messagePattern":"Wan latents-to-video expects a 5D latent tensor \\[B, C, T, H, W\\]; got (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/wan_latents_to_video.py","lineNumber":99,"sourceCode":"    latents: LatentsField = InputField(description=FieldDescriptions.latents, input=Input.Connection)\n    vae: VAEField = InputField(description=FieldDescriptions.vae, input=Input.Connection)\n    fps: int = InputField(\n        default=16,\n        ge=1,\n        le=120,\n        description=\"Frames-per-second for the encoded MP4. Wan 2.2 was trained at 16 FPS.\",\n    )\n\n    @torch.no_grad()\n    def invoke(self, context: InvocationContext) -> VideoOutput:\n        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","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/wan_latents_to_video.py#L81-L117","documentation":"After promoting 4D tensors to 5D, invoke() requires the latent tensor to be rank 5 ([B, C, T, H, W]). Anything else (1D, 2D, 3D, or 6D+) cannot be interpreted as video latents, so a ValueError with the actual shape tuple is raised.","triggerScenarios":"Passing a tensor of ndim other than 4 or 5 into wan_latents_to_video — e.g. a 2D noise tensor, an image-latent [B,C,H,W] mis-shaped into 3D, or a corrupted tensor from an upstream node.","commonSituations":"Wiring an image latents node (4D) through reshaping that drops dims; feeding raw noise instead of denoiser output; version drift where an upstream node changed its output rank.","solutions":["Ensure the input is a Wan denoiser output of rank 5 [B, C, T, H, W].","If you have single-frame 4D latents [B,C,H,W], the node auto-promotes them — verify no extra squeeze/dim edits occurred upstream.","Print latents.shape before invoking and reshape correctly (e.g. latents.unsqueeze(0) for a missing batch dim)."],"exampleFix":"// before\nlatents = torch.randn(16, 8, 64)  # 3D, invalid\nvideo = wan_latents_to_video(latents=latents)\n// after\nlatents = torch.randn(1, 16, 8, 64, 64)  # [B, C, T, H, W]\nvideo = wan_latents_to_video(latents=latents)","handlingStrategy":"validation","validationCode":"if latents.ndim not in (4, 5):\n    raise ValueError(f\"Expected 4D or 5D Wan latents, got shape {tuple(latents.shape)}\")","typeGuard":"def is_video_latent_tensor(t) -> bool:\n    return isinstance(t, torch.Tensor) and t.ndim in (4, 5)","tryCatchPattern":"try:\n    video = node.invoke(context)\nexcept ValueError as e:\n    if \"5D latent tensor\" in str(e):\n        latents = fix_rank(latents)  # e.g. unsqueeze(0) for missing batch\n        video = node.invoke(context)\n    else:\n        raise","preventionTips":["Feed only Wan denoiser outputs into the video node.","Avoid ad-hoc squeeze/reshape between denoiser and video node.","Log tensor shapes at workflow boundaries.","Use type-checked graph connections where possible."],"tags":["wan","tensor-shape","validation","video"],"backgroundTag":"tensor-rank-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}