{"record":{"id":"68b4bd49d98f9bb8","repo":"invoke-ai/InvokeAI","slug":"wan-vae-decode-produced-num-frames-frames-expec","errorCode":null,"errorMessage":"Wan VAE decode produced {num_frames} frames; expected {t_pixel}.","messagePattern":"Wan VAE decode produced (.+?) frames; expected (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/wan_latents_to_video.py","lineNumber":224,"sourceCode":"                                writer.close()\n                        else:\n                            # [C=3, T_pixel, H, W] in [-1, 1] (roughly), on CPU.\n                            decoded = vae.decode(latents, return_dict=False)[0][0].cpu()\n                            num_frames = decoded.shape[1]\n                        del latents, latents_mean, latents_std\n                finally:\n                    # The VAE instance is cached and shared; don't leak tiling into other nodes.\n                    if use_tiling:\n                        vae.disable_tiling()\n\n            TorchDevice.empty_cache()\n\n            if context.util.is_canceled():\n                raise CanceledException\n            if num_frames == 0:\n                raise ValueError(\"Wan VAE decode produced zero frames.\")\n            if num_frames != t_pixel:\n                raise ValueError(f\"Wan VAE decode produced {num_frames} frames; expected {t_pixel}.\")\n\n            height, width = h_pixel, w_pixel\n            duration = num_frames / float(self.fps)\n            if decoded is not None:\n                context.logger.info(\n                    f\"Encoding MP4: {num_frames} frames @ {self.fps} fps \"\n                    f\"({duration:.2f}s) at {width}x{height} via libx264\"\n                )\n                context.util.signal_progress(f\"Encoding MP4 ({num_frames} frames @ {self.fps} fps)\")\n                writer = make_mp4_writer(tmp_path, self.fps)\n                try:\n                    _write_video_frames(writer, _iter_decoded_frames(decoded), context.util.is_canceled)\n                finally:\n                    writer.close()\n                del decoded\n                TorchDevice.empty_cache()\n\n            encoded_bytes = tmp_path.stat().st_size","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/wan_latents_to_video.py#L206-L242","documentation":"invoke() verifies that the frame count produced by the Wan VAE decode equals t_pixel, the expected pixel-space temporal length computed from the latent temporal dim and Wan's temporal scaling. A mismatch means the decode's frame math diverged from expectations, so a ValueError reports both actual and expected counts.","triggerScenarios":"Decoding latents where the Wan temporal expansion factor (e.g. 4x plus FirstFrame handling) does not match the computed t_pixel — e.g. non-standard frame counts, a VAE version with different temporal behavior, or manually crafted latents with inconsistent T.","commonSituations":"Choosing frame counts not conformant to Wan's (4k+1) convention; swapping between Wan 2.1 and 2.2 VAEs with different temporal scaling; hand-edited latent tensors.","solutions":["Use frame counts matching Wan's convention (e.g. 4*n+1 frames) so t_pixel matches decode output.","Verify the VAE/diffusers version's temporal expansion matches the node's expectation.","Let the upstream Wan denoiser compute the latent T rather than crafting latents manually.","Log latents.shape and expected t_pixel to diagnose the off-by-N and adjust num_frames."],"exampleFix":"// before\nlatents = denoise(num_frames=10)  # decode -> 40 frames, expected 41\nvideo = wan_latents_to_video(latents=latents)  # ValueError\n// after\nlatents = denoise(num_frames=9)  # conformant count; decode -> expected frames\nvideo = wan_latents_to_video(latents=latents)","handlingStrategy":"validation","validationCode":"t_pixel = (latents.shape[2] - 1) * 4 + 1\nif num_frames_expected != t_pixel:\n    raise ValueError(f\"frame math off: expect {t_pixel}, config says {num_frames_expected}\")","typeGuard":"def frame_count_conformant(n: int) -> bool:\n    return n >= 1 and (n - 1) % 4 == 0","tryCatchPattern":"try:\n    video = node.invoke(context)\nexcept ValueError as e:\n    if \"frames; expected\" in str(e):\n        adjust_num_frames_to_convention()  # use 4k+1 counts\n        video = node.invoke(context)\n    else:\n        raise","preventionTips":["Stick to Wan's (4k+1) frame-count convention.","Don't hand-edit latent temporal dims.","Keep the same Wan generation (2.1 vs 2.2) across denoiser and VAE.","Compute expected frames from latent T rather than hardcoding."],"tags":["wan","frame-count","vae-decode","video"],"backgroundTag":"frame-count-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}