invoke-ai/InvokeAI · error · ValueError
num_frames must satisfy (num_frames - 1) %% 4 == 0 for the W
Error message
num_frames must satisfy (num_frames - 1) %% 4 == 0 for the Wan VAE's temporal compression (got {self.num_frames}). Try 5, 9, 13, ..., 81, 85, ... What it means
The Wan Reference Image invocation validates that the requested video frame count is compatible with the Wan VAE's 4x temporal compression: the latent time axis requires (num_frames - 1) to be divisible by 4. InvokeAI raises this ValueError before any encoding work so the user gets an immediate, actionable message instead of a cryptic shape mismatch deep in the VAE.
Source
Thrown at invokeai/app/invocations/wan_ref_image_encoder.py:110
default=1,
ge=1,
description="Pixel-frame count to build the condition for. Use 1 for single-frame image "
"I2V. For video I2V, set this to match the video-denoise node's num_frames (and ensure "
"(num_frames - 1) %% 4 == 0, e.g. 81).",
title="Number of Frames",
)
end_image: Optional[ImageField] = InputField(
default=None,
description="Optional end frame for first-last-frame interpolation (FLF2V). When set, the "
"video interpolates from the reference image (first frame) to this image (final frame). "
"I2V-A14B video only (num_frames > 1); not supported for TI2V-5B or single-frame I2V.",
title="End Image (FLF2V)",
)
@torch.no_grad()
def invoke(self, context: InvocationContext) -> WanRefImageOutput:
if self.num_frames > 1 and (self.num_frames - 1) % 4 != 0:
raise ValueError(
f"num_frames must satisfy (num_frames - 1) %% 4 == 0 for the Wan VAE's temporal "
f"compression (got {self.num_frames}). Try 5, 9, 13, ..., 81, 85, ..."
)
pil_image = context.images.get_pil(self.image.image_name, "RGB")
end_pil_image = context.images.get_pil(self.end_image.image_name, "RGB") if self.end_image is not None else None
vae_info = context.models.load(self.vae.vae)
if not isinstance(vae_info.model, AutoencoderKLWan):
raise TypeError(f"Reference-image encoder requires AutoencoderKLWan, got {type(vae_info.model).__name__}.")
estimated_working_memory = estimate_vae_working_memory_wan(
operation="encode",
vae=vae_info.model,
pixel_height=self.height,
pixel_width=self.width,
pixel_frames=self.num_frames,
)View on GitHub (pinned to 0b6a024f2f)
Solutions
- Change num_frames to the nearest valid value of the form 4n+1 (5, 9, 13, 17, ..., 81, 85).
- If you need exactly 60 frames, render 57 or 61 frames and trim/duplicate one frame in post.
- Keep num_frames = 1 for single-frame image conditioning, which bypasses the check.
Example fix
// before num_frames = 60 # (60 - 1) % 4 != 0 // after num_frames = 61 # 4n+1, valid for Wan VAE temporal compression
Defensive patterns
Strategy: validation
Validate before calling
def valid_wan_num_frames(n: int) -> bool:
return n == 1 or (n - 1) % 4 == 0
if not valid_wan_num_frames(num_frames):
num_frames = max(5, ((num_frames - 1) // 4) * 4 + 1) Try / catch
try:
out = encoder.invoke(context)
except ValueError as e:
if "num_frames must satisfy" in str(e):
num_frames = ((num_frames - 1) // 4) * 4 + 1 # snap to 4n+1
else:
raise Prevention
- Always pick frame counts from the 4n+1 sequence (5, 9, 13, ..., 81, 85).
- Derive duration from frames, not frames from duration: frames = 4*seconds*fps_rounded + 1 style snapping.
- Share one num_frames value between encoder and denoise nodes.
When it happens
Trigger: Calling the 'Reference Image - Wan 2.2' (wan_ref_image_encoder) invocation with num_frames set to a value > 1 where (num_frames - 1) % 4 != 0, e.g. 6, 10, 30, 60.
Common situations: Users pick '60 frames for 2 seconds at 30fps' or copy frame counts from other video tools whose VAEs don't have the 4x temporal constraint; only 4n+1 counts (5, 9, 13, ..., 81, 85) are valid.
Related errors
- num_frames must satisfy (num_frames - 1) %% 4 == 0 for the W
- Wan latents-to-video requires batch size 1; got {latents.sha
- Wan latents-to-video expects a 5D latent tensor [B, C, T, H,
- Wan latents-to-video requires non-empty temporal and spatial
- Reference-image num_frames ({self.ref_image.num_frames}) mus
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/9ee66807895ef4f6.
Report an issue: GitHub.