invoke-ai/InvokeAI · error · ValueError
Qwen-Image PiD decode expected a single temporal frame, got
Error message
Qwen-Image PiD decode expected a single temporal frame, got shape {tuple(latents.shape)}. What it means
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.
Source
Thrown at invokeai/app/invocations/qwen_image_pid_decode.py:130
seed: int = InputField(default=0, description="Seed for the PiD decoder's noise.")
@torch.no_grad()
def invoke(self, context: InvocationContext) -> ImageOutput:
# Fail fast if the connected decoder is for a different backbone (the base-agnostic loader lets
# the Nodes editor wire any PiD decoder into this Qwen-Image-specific node).
assert_pid_decoder_matches_base(
context.models.get_config(self.pid_decoder.decoder).base,
BaseModelType.QwenImage,
node_title="Qwen-Image PiD Decode",
)
latents = context.tensors.load(self.latents.latents_name)
# 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
# autoencoder; for a single image num_frames == 1 (mirrors qwen_image_l2i's `img[:, :, 0]`).
if latents.ndim == 5:
if latents.shape[2] != 1:
raise ValueError(
f"Qwen-Image PiD decode expected a single temporal frame, got shape {tuple(latents.shape)}."
)
latents = latents[:, :, 0]
if latents.ndim != 4 or latents.shape[-3] != 16:
raise ValueError(f"Qwen-Image PiD decode expected a 16-channel latent, got shape {tuple(latents.shape)}.")
# 2) Resolve the per-channel latents_mean / latents_std used to denormalise the stored latent.
latents_mean = list(_QWEN_VAE_LATENTS_MEAN_FALLBACK)
latents_std = list(_QWEN_VAE_LATENTS_STD_FALLBACK)
if self.vae is not None:
vae_info = context.models.load(self.vae.vae)
with vae_info.model_on_device() as (_, vae):
config = getattr(vae, "config", None)
cfg_mean = getattr(config, "latents_mean", None) if config is not None else None
cfg_std = getattr(config, "latents_std", None) if config is not None else None
if cfg_mean is not None and cfg_std is not None:
latents_mean = [float(x) for x in cfg_mean]
latents_std = [float(x) for x in cfg_std]View on GitHub (pinned to 0b6a024f2f)
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
Example fix
// before latents = latents # (B, C, 8, H, W) video latent // after latents = latents[:, :, 0] # reduce to (B, C, H, W) before decode
Defensive patterns
Strategy: type-guard
Validate before calling
latents = context.tensors.load(latents_name)
if latents.ndim == 5 and latents.shape[2] != 1:
raise ValueError(f"PiD decode needs single-frame latents, got {tuple(latents.shape)}") Type guard
def is_single_frame_image_latent(t: "torch.Tensor") -> bool:
if t.ndim == 5:
return t.shape[2] == 1
return t.ndim == 4 Try / catch
try:
output = invoke(context)
except ValueError as e:
if "single temporal frame" in str(e):
latents = context.tensors.load(node.latents.latents_name)[:, :, 0]
# re-save / retry with reduced latent
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Qwen-Image PiD decode expected a 16-channel latent, got shap
- Model '{model_key}' is not a TextLLM model (got {model_confi
- Model '{model_key}' is not a LLaVA OneVision model (got {mod
- No VAE source provided. Standalone safetensors/GGUF models r
- VAE '{vae_config.name}' is not compatible with Krea-2. Selec
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/83c1119942d5bb78.
Report an issue: GitHub.