invoke-ai/InvokeAI · error · ValueError

degrade_sigma must broadcast to [B={batch_size}], got shape

Error message

degrade_sigma must broadcast to [B={batch_size}], got shape {tuple(degrade_sigma_t.shape)}

What it means

decode() normalizes the degrade_sigma argument into a 1-D float32 tensor of length batch_size (scalar, sequence, or expandable tensor). If the resulting tensor's shape does not equal (batch_size,), it raises ValueError because the per-batch sigma schedule cannot be aligned with the latents.

Source

Thrown at invokeai/backend/pid/decode.py:532

        # space at sr_scale * latent_spatial_down_factor times the latent.
        total_up = self.sr_scale * self.latent_spatial_down_factor
        img_h = int(latent.shape[-2] * total_up)
        img_w = int(latent.shape[-1] * total_up)

        gen = torch.Generator(device=device).manual_seed(int(cfg.seed))
        noise = torch.randn(batch_size, 3, img_h, img_w, device=device, generator=gen, dtype=dtype)

        sigma = cfg.degrade_sigma
        if isinstance(sigma, Tensor):
            degrade_sigma_t = sigma.to(device=device, dtype=torch.float32).reshape(-1)
            if degrade_sigma_t.numel() == 1:
                degrade_sigma_t = degrade_sigma_t.expand(batch_size).contiguous()
        elif isinstance(sigma, (list, tuple)):
            degrade_sigma_t = torch.tensor(sigma, device=device, dtype=torch.float32)
        else:
            degrade_sigma_t = torch.full((batch_size,), float(sigma), device=device, dtype=torch.float32)
        if degrade_sigma_t.shape != (batch_size,):
            raise ValueError(
                f"degrade_sigma must broadcast to [B={batch_size}], got shape {tuple(degrade_sigma_t.shape)}"
            )

        caption_embs = caption_embs.to(device=device, dtype=dtype)
        if caption_mask is not None:
            caption_mask = caption_mask.to(device=device)
        lq_latent = latent.to(device=device, dtype=dtype)

        t_list = _get_t_list(device, num_steps=cfg.num_inference_steps)

        if cfg.pid_memory_optimization:
            # The setting is server-level and never reaches image metadata, so this log line is the
            # only record that a decode ran optimized - and the only feedback the user gets that a
            # yaml-only, restart-required knob took effect. It also reports whether chunking really
            # engaged: below the chunk size the pixel blocks run unchunked and only the sampler-math
            # change applies.
            patch_tokens = batch_size * (img_h // self.net.patch_size) * (img_w // self.net.patch_size)
            engaged = patch_tokens > _PID_ACTIVATION_CHUNK_SIZE

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Pass a scalar float for degrade_sigma so it fills a [B] tensor automatically
  2. Pass a list/tuple or 1-D tensor with exactly batch_size elements
  3. Ensure a tensor input is shape (batch_size,) or broadcastable via .expand(batch_size) before calling

Example fix

// before
decoder.decode(latent, caption_embs, degrade_sigma=torch.randn(4, 1))
// after
decoder.decode(latent, caption_embs, degrade_sigma=torch.full((4,), 0.5))
Defensive patterns

Strategy: validation

Validate before calling

b = latent.shape[0]
if isinstance(degrade_sigma, torch.Tensor):
    degrade_sigma = degrade_sigma.reshape(-1)
    assert degrade_sigma.numel() == 1 or degrade_sigma.numel() == b, "sigma must be scalar or length B"
decoder.decode(latent=latent, caption_embs=embs, degrade_sigma=degrade_sigma)

Type guard

def sigma_broadcasts(sigma, batch_size: int) -> bool:
    if isinstance(sigma, (int, float)):
        return True
    if isinstance(sigma, (list, tuple)):
        return len(sigma) == batch_size
    if isinstance(sigma, torch.Tensor):
        return sigma.numel() in (1, batch_size)
    return False

Try / catch

try:
    image = decoder.decode(latent=lat, caption_embs=embs, degrade_sigma=sigma)
except ValueError as e:
    logger.error(str(e)); image = None

Prevention

When it happens

Trigger: Calling decoder.decode(..., degrade_sigma=tensor_of_wrong_shape) where sigma has extra dims or a length different from the latent batch size, and it cannot be expanded to [B].

Common situations: Passing a per-image sigma list whose length differs from the latent batch; passing a 2-D tensor like [B,1] that torch.expand cannot squeeze to 1-D; copying sigma from a different batch size when reusing a batched call.

Understand the failure class

Background: Tensor shape mismatch errors ("must have shape", "expected shape ... got ..."): when tensor dimensions disagree with what an op or layer was told to expect — this error's family across 6 libraries.

Related errors


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