{"record":{"id":"cba1f6b8aee0af31","repo":"invoke-ai/InvokeAI","slug":"last-image-flf2v-interpolation-requires-num-fram","errorCode":null,"errorMessage":"last_image (FLF2V) interpolation requires num_frames > 1.","messagePattern":"last_image \\(FLF2V\\) interpolation requires num_frames > 1\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/wan/extensions/wan_ref_image_extension.py","lineNumber":167,"sourceCode":"    1. The reference image is concatenated with zero pixel-frames to form a\n       ``[1, 3, num_frames, H, W]`` pseudo-video — frame 0 carries the start\n       image, frame ``num_frames - 1`` carries ``last_image`` (when given), and\n       the frames in between are zero. The model was trained against latents\n       produced this way; padding in latent space after a 1-frame VAE encode\n       would land different values.\n    2. The VAE encodes that to ``[1, 16, T_lat, H_lat, W_lat]`` and we\n       normalise by the per-channel ``(mean, std)`` from ``vae.config``.\n    3. The mask starts in pixel-frame space as ``[1, 1, num_frames, ...]``\n       with 1 at the anchored frame(s) and 0 elsewhere — frame 0 for plain I2V,\n       or frames 0 and ``num_frames - 1`` for FLF2V. The first frame is repeated\n       4× then the whole thing is reshaped/transposed into ``[1, 4, T_lat, ...]``.\n\n    The denoise loop concatenates the result along the channel dim to the\n    16-channel noise latents each step, yielding the 36-channel input the\n    Wan 2.2 I2V-A14B transformer expects.\n    \"\"\"\n    if last_image is not None and num_frames <= 1:\n        raise ValueError(\"last_image (FLF2V) interpolation requires num_frames > 1.\")\n\n    vae_dtype = next(iter(vae.parameters())).dtype\n    pixel = preprocess_reference_image(image, width=width, height=height).to(\n        device=device, dtype=vae_dtype\n    )  # [1, 3, 1, H, W]\n\n    # Pad the temporal dim with zero pixel-frames; the VAE handles temporal\n    # compression to T_lat. For FLF2V the end image takes the final slot and\n    # only the in-between frames are zero.\n    if num_frames > 1:\n        if last_image is not None:\n            last_pixel = preprocess_reference_image(last_image, width=width, height=height).to(\n                device=device, dtype=vae_dtype\n            )\n            middle_zeros = torch.zeros(1, 3, num_frames - 2, height, width, device=device, dtype=vae_dtype)\n            video_condition = torch.cat([pixel, middle_zeros, last_pixel], dim=2)\n        else:\n            zero_frames = torch.zeros(1, 3, num_frames - 1, height, width, device=device, dtype=vae_dtype)","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/wan/extensions/wan_ref_image_extension.py#L149-L185","documentation":"encode_reference_image_to_video_condition supports FLF2V (first-last-frame-to-video): when a last_image is supplied it is encoded and anchored at the final latent frame. With num_frames == 1 there is no temporal span to interpolate across and only one anchor slot, so the function raises this ValueError instead of silently dropping the last image.","triggerScenarios":"Calling encode_reference_image_to_video_condition with last_image set but num_frames=1 (or 0/negative), e.g. single-frame video generation while also passing an end frame.","commonSituations":"Configuring a one-frame clip by mistake, computing num_frames from an FPS/duration that rounds to 1, reusing an I2V code path where num_frames defaults to 1 while adding an FLF2V last frame.","solutions":["Increase num_frames to at least 2 (Wan typically expects values like 81 for FLF2V).","If you truly want a single frame, pass last_image=None and use the plain I2V path.","Check how num_frames is computed (fps * duration) and ensure rounding yields > 1."],"exampleFix":"// before\nencode_reference_image_to_video_condition(..., num_frames=1, last_image=end_img)\n// after\nencode_reference_image_to_video_condition(..., num_frames=81, last_image=end_img)","handlingStrategy":"validation","validationCode":"if last_image is not None and num_frames <= 1:\n    raise ValueError(\"FLF2V needs num_frames > 1; got %d\" % num_frames)\nlatents = encode_reference_image_to_video_condition(..., num_frames=num_frames, last_image=last_image)","typeGuard":null,"tryCatchPattern":"try:\n    cond = encode_reference_image_to_video_condition(..., num_frames=n, last_image=last_img)\nexcept ValueError as e:\n    if \"requires num_frames > 1\" in str(e):\n        cond = encode_reference_image_to_video_condition(..., num_frames=max(2, n), last_image=last_img)","preventionTips":["Compute num_frames as max(2, round(fps * duration)) and prefer Wan-standard counts like 81.","Pass last_image only when you intend FLF2V generation with multiple frames.","Unit-test the fps/duration -> num_frames calculation with edge values."],"tags":["python","video","wan","flf2v","validation"],"backgroundTag":"invalid-parameter-combination","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}