{"record":{"id":"83c1119942d5bb78","repo":"invoke-ai/InvokeAI","slug":"qwen-image-pid-decode-expected-a-single-temporal-f","errorCode":null,"errorMessage":"Qwen-Image PiD decode expected a single temporal frame, got shape {tuple(latents.shape)}.","messagePattern":"Qwen-Image PiD decode expected a single temporal frame, got shape (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/qwen_image_pid_decode.py","lineNumber":130,"sourceCode":"    seed: int = InputField(default=0, description=\"Seed for the PiD decoder's noise.\")\n\n    @torch.no_grad()\n    def invoke(self, context: InvocationContext) -> ImageOutput:\n        # Fail fast if the connected decoder is for a different backbone (the base-agnostic loader lets\n        # the Nodes editor wire any PiD decoder into this Qwen-Image-specific node).\n        assert_pid_decoder_matches_base(\n            context.models.get_config(self.pid_decoder.decoder).base,\n            BaseModelType.QwenImage,\n            node_title=\"Qwen-Image PiD Decode\",\n        )\n\n        latents = context.tensors.load(self.latents.latents_name)\n\n        # 1) Reduce the stored 5D (B, C, num_frames, H, W) latent to 2D (B, C, H, W). Qwen's VAE is a video-style\n        #    autoencoder; for a single image num_frames == 1 (mirrors qwen_image_l2i's `img[:, :, 0]`).\n        if latents.ndim == 5:\n            if latents.shape[2] != 1:\n                raise ValueError(\n                    f\"Qwen-Image PiD decode expected a single temporal frame, got shape {tuple(latents.shape)}.\"\n                )\n            latents = latents[:, :, 0]\n        if latents.ndim != 4 or latents.shape[-3] != 16:\n            raise ValueError(f\"Qwen-Image PiD decode expected a 16-channel latent, got shape {tuple(latents.shape)}.\")\n\n        # 2) Resolve the per-channel latents_mean / latents_std used to denormalise the stored latent.\n        latents_mean = list(_QWEN_VAE_LATENTS_MEAN_FALLBACK)\n        latents_std = list(_QWEN_VAE_LATENTS_STD_FALLBACK)\n        if self.vae is not None:\n            vae_info = context.models.load(self.vae.vae)\n            with vae_info.model_on_device() as (_, vae):\n                config = getattr(vae, \"config\", None)\n                cfg_mean = getattr(config, \"latents_mean\", None) if config is not None else None\n                cfg_std = getattr(config, \"latents_std\", None) if config is not None else None\n                if cfg_mean is not None and cfg_std is not None:\n                    latents_mean = [float(x) for x in cfg_mean]\n                    latents_std = [float(x) for x in cfg_std]","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/qwen_image_pid_decode.py#L112-L148","documentation":"QwenImagePiDDecodeInvocation loads stored latents and, if they are 5D video-style (B, C, num_frames, H, W), requires num_frames == 1 because this path decodes a single image. A temporal-frame count other than 1 cannot be reduced via latents[:, :, 0], so it raises ValueError with the full latent shape.","triggerScenarios":"Wiring a PiD decode node to latents produced by a video sampler (num_frames > 1), or latents saved with an unexpected frame dimension, then invoking the node.","commonSituations":"Reusing a Qwen video workflow's latent output in an image decode node; a graph edit changed frame count but kept the PiD decode; loading a latents file generated with a different pipeline.","solutions":["Feed the node latents with exactly one temporal frame (single-image generation)","Slice/select frame 0 upstream (e.g. with a latent select node) before decoding","Verify the producing node is an image, not video, Qwen pipeline","Check the latents_name tensor shape in context.tensors to confirm dimensions"],"exampleFix":"// before\nlatents = latents  # (B, C, 8, H, W) video latent\n// after\nlatents = latents[:, :, 0]  # reduce to (B, C, H, W) before decode","handlingStrategy":"type-guard","validationCode":"latents = context.tensors.load(latents_name)\nif latents.ndim == 5 and latents.shape[2] != 1:\n    raise ValueError(f\"PiD decode needs single-frame latents, got {tuple(latents.shape)}\")","typeGuard":"def is_single_frame_image_latent(t: \"torch.Tensor\") -> bool:\n    if t.ndim == 5:\n        return t.shape[2] == 1\n    return t.ndim == 4","tryCatchPattern":"try:\n    output = invoke(context)\nexcept ValueError as e:\n    if \"single temporal frame\" in str(e):\n        latents = context.tensors.load(node.latents.latents_name)[:, :, 0]\n        # re-save / retry with reduced latent\n    else:\n        raise","preventionTips":["Only wire image (single-frame) Qwen latents into PiD decode","Check latent tensor shape before connecting nodes in the editor","Keep video and image workflows as separate graphs"],"tags":["invokeai","qwen-image","vae","latent-shape","valueerror"],"backgroundTag":"latent-shape-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}