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

  1. Feed the node latents with exactly one temporal frame (single-image generation)
  2. Slice/select frame 0 upstream (e.g. with a latent select node) before decoding
  3. Verify the producing node is an image, not video, Qwen pipeline
  4. 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

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


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/83c1119942d5bb78. Report an issue: GitHub.