invoke-ai/InvokeAI · error · ValueError

Wan VAE decode produced {num_frames} frames; expected {t_pix

Error message

Wan VAE decode produced {num_frames} frames; expected {t_pixel}.

What it means

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.

Source

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

                                writer.close()
                        else:
                            # [C=3, T_pixel, H, W] in [-1, 1] (roughly), on CPU.
                            decoded = vae.decode(latents, return_dict=False)[0][0].cpu()
                            num_frames = decoded.shape[1]
                        del latents, latents_mean, latents_std
                finally:
                    # The VAE instance is cached and shared; don't leak tiling into other nodes.
                    if use_tiling:
                        vae.disable_tiling()

            TorchDevice.empty_cache()

            if context.util.is_canceled():
                raise CanceledException
            if num_frames == 0:
                raise ValueError("Wan VAE decode produced zero frames.")
            if num_frames != t_pixel:
                raise ValueError(f"Wan VAE decode produced {num_frames} frames; expected {t_pixel}.")

            height, width = h_pixel, w_pixel
            duration = num_frames / float(self.fps)
            if decoded is not None:
                context.logger.info(
                    f"Encoding MP4: {num_frames} frames @ {self.fps} fps "
                    f"({duration:.2f}s) at {width}x{height} via libx264"
                )
                context.util.signal_progress(f"Encoding MP4 ({num_frames} frames @ {self.fps} fps)")
                writer = make_mp4_writer(tmp_path, self.fps)
                try:
                    _write_video_frames(writer, _iter_decoded_frames(decoded), context.util.is_canceled)
                finally:
                    writer.close()
                del decoded
                TorchDevice.empty_cache()

            encoded_bytes = tmp_path.stat().st_size

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Use frame counts matching Wan's convention (e.g. 4*n+1 frames) so t_pixel matches decode output.
  2. Verify the VAE/diffusers version's temporal expansion matches the node's expectation.
  3. Let the upstream Wan denoiser compute the latent T rather than crafting latents manually.
  4. Log latents.shape and expected t_pixel to diagnose the off-by-N and adjust num_frames.

Example fix

// before
latents = denoise(num_frames=10)  # decode -> 40 frames, expected 41
video = wan_latents_to_video(latents=latents)  # ValueError
// after
latents = denoise(num_frames=9)  # conformant count; decode -> expected frames
video = wan_latents_to_video(latents=latents)
Defensive patterns

Strategy: validation

Validate before calling

t_pixel = (latents.shape[2] - 1) * 4 + 1
if num_frames_expected != t_pixel:
    raise ValueError(f"frame math off: expect {t_pixel}, config says {num_frames_expected}")

Type guard

def frame_count_conformant(n: int) -> bool:
    return n >= 1 and (n - 1) % 4 == 0

Try / catch

try:
    video = node.invoke(context)
except ValueError as e:
    if "frames; expected" in str(e):
        adjust_num_frames_to_convention()  # use 4k+1 counts
        video = node.invoke(context)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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