{"record":{"id":"9ee66807895ef4f6","repo":"invoke-ai/InvokeAI","slug":"num-frames-must-satisfy-num-frames-1-4-0","errorCode":null,"errorMessage":"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, ...","messagePattern":"num_frames must satisfy \\(num_frames - 1\\) %% 4 == 0 for the Wan VAE's temporal compression \\(got (.+?)\\)\\. Try 5, 9, 13, \\.\\.\\., 81, 85, \\.\\.\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/wan_ref_image_encoder.py","lineNumber":110,"sourceCode":"        default=1,\n        ge=1,\n        description=\"Pixel-frame count to build the condition for. Use 1 for single-frame image \"\n        \"I2V. For video I2V, set this to match the video-denoise node's num_frames (and ensure \"\n        \"(num_frames - 1) %% 4 == 0, e.g. 81).\",\n        title=\"Number of Frames\",\n    )\n    end_image: Optional[ImageField] = InputField(\n        default=None,\n        description=\"Optional end frame for first-last-frame interpolation (FLF2V). When set, the \"\n        \"video interpolates from the reference image (first frame) to this image (final frame). \"\n        \"I2V-A14B video only (num_frames > 1); not supported for TI2V-5B or single-frame I2V.\",\n        title=\"End Image (FLF2V)\",\n    )\n\n    @torch.no_grad()\n    def invoke(self, context: InvocationContext) -> WanRefImageOutput:\n        if self.num_frames > 1 and (self.num_frames - 1) % 4 != 0:\n            raise ValueError(\n                f\"num_frames must satisfy (num_frames - 1) %% 4 == 0 for the Wan VAE's temporal \"\n                f\"compression (got {self.num_frames}). Try 5, 9, 13, ..., 81, 85, ...\"\n            )\n\n        pil_image = context.images.get_pil(self.image.image_name, \"RGB\")\n        end_pil_image = context.images.get_pil(self.end_image.image_name, \"RGB\") if self.end_image is not None else None\n\n        vae_info = context.models.load(self.vae.vae)\n        if not isinstance(vae_info.model, AutoencoderKLWan):\n            raise TypeError(f\"Reference-image encoder requires AutoencoderKLWan, got {type(vae_info.model).__name__}.\")\n\n        estimated_working_memory = estimate_vae_working_memory_wan(\n            operation=\"encode\",\n            vae=vae_info.model,\n            pixel_height=self.height,\n            pixel_width=self.width,\n            pixel_frames=self.num_frames,\n        )","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/wan_ref_image_encoder.py#L92-L128","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nnum_frames = 60  # (60 - 1) % 4 != 0\n// after\nnum_frames = 61  # 4n+1, valid for Wan VAE temporal compression","handlingStrategy":"validation","validationCode":"def valid_wan_num_frames(n: int) -> bool:\n    return n == 1 or (n - 1) % 4 == 0\nif not valid_wan_num_frames(num_frames):\n    num_frames = max(5, ((num_frames - 1) // 4) * 4 + 1)","typeGuard":null,"tryCatchPattern":"try:\n    out = encoder.invoke(context)\nexcept ValueError as e:\n    if \"num_frames must satisfy\" in str(e):\n        num_frames = ((num_frames - 1) // 4) * 4 + 1  # snap to 4n+1\n    else:\n        raise","preventionTips":["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."],"tags":["validation","video","num-frames","wan"],"backgroundTag":"invalid-num-frames-wan-vae","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}