{"record":{"id":"b0abdc5751cc02d9","repo":"invoke-ai/InvokeAI","slug":"qwen-image-pid-decode-expected-a-16-channel-latent","errorCode":null,"errorMessage":"Qwen-Image PiD decode expected a 16-channel latent, got shape {tuple(latents.shape)}.","messagePattern":"Qwen-Image PiD decode expected a 16-channel latent, got shape (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/qwen_image_pid_decode.py","lineNumber":135,"sourceCode":"        # 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]\n            del vae_info\n            TorchDevice.empty_cache()\n        if len(latents_mean) != 16 or len(latents_std) != 16:\n            raise ValueError(\n                f\"Qwen-Image VAE latents_mean/latents_std must have 16 entries, got {len(latents_mean)}/{len(latents_std)}.\"","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/qwen_image_pid_decode.py#L117-L153","documentation":"After frame reduction the invocation validates the latent is 4D with 16 channels (Qwen-Image latent channel count). Anything else (SD-style 4-channel, video latent not reduced, wrong ndim) raises ValueError reporting the actual shape, since the VAE denormalization/decode expects exactly this layout.","triggerScenarios":"Connecting latents from a non-Qwen model (e.g. SD 4-channel) to the Qwen PiD decode node; passing a 5D latent whose ndim/shape wasn't reduced; loading a stale latents file from another pipeline.","commonSituations":"Mixing model families in one graph (SDXL denoise -> Qwen decode); upgrading InvokeAI where channel conventions changed; hand-edited workflows with mismatched latent nodes.","solutions":["Ensure the upstream denoise/latent node is the Qwen-Image pipeline producing 16-channel 4D latents","Check latents.shape: must be (B, 16, H, W) after any frame reduction","Use the correct model-specific decode node for non-Qwen latents instead of PiD decode","Regenerate the latents with the correct pipeline rather than reusing an old latents_name"],"exampleFix":"// before\nlatents = latents  # (1, 4, 64, 64) SD latent fed to Qwen decode\n// after\nlatents = qwen_denoise.latents  # (1, 16, H, W) Qwen latent","handlingStrategy":"type-guard","validationCode":"latents = context.tensors.load(latents_name)\nassert latents.ndim == 4 and latents.shape[-3] == 16, f\"bad latent: {tuple(latents.shape)}\"","typeGuard":"def is_qwen_image_latent(t: \"torch.Tensor\") -> bool:\n    return t.ndim == 4 and t.shape[-3] == 16","tryCatchPattern":"try:\n    output = invoke(context)\nexcept ValueError as e:\n    if \"16-channel latent\" in str(e):\n        raise RuntimeError(\"Wire a Qwen-Image 16-channel latent into this node\") from e\n    raise","preventionTips":["Match decode nodes to the model family that produced the latents","Never reuse SD/SDXL 4-channel latents in Qwen nodes","Verify latent channel count when importing workflows from other versions"],"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"}