invoke-ai/InvokeAI · error · ValueError
Unexpected mask shape: {tuple(mask_b1hw_01.shape)} (expected
Error message
Unexpected mask shape: {tuple(mask_b1hw_01.shape)} (expected B,H,W or B,1,H,W) What it means
prepare_mask accepts a mask as (B,H,W) or (B,1,H,W) floats in [0,1]; anything else raises ValueError. It binarizes at 0.5 and resizes (nearest) to the latent-derived spatial target, so it must be able to interpret the tensor's layout unambiguously.
Source
Thrown at invokeai/backend/anima/control_net_lllite.py:100
target_h, target_w = target_cond_hw(latent_h, latent_w, patch_spatial)
if img.shape[-2] != target_h or img.shape[-1] != target_w:
img = F.interpolate(img, size=(target_h, target_w), mode="bicubic", align_corners=False)
img = img.clamp(0.0, 1.0)
return img * 2.0 - 1.0
def prepare_mask(mask_b1hw_01: torch.Tensor, latent_h: int, latent_w: int, patch_spatial: int = 2) -> torch.Tensor:
"""Mask (B, 1, H, W) or (B, H, W) in [0, 1] -> (1, 1, H_t, W_t) in {0.0, 1.0}.
1 = inpaint area, 0 = keep. The caller is responsible for the ``*2-1``
rescale before concat with RGB (see :func:`build_inpaint_cond_image`).
"""
if mask_b1hw_01.ndim == 3:
m = mask_b1hw_01.unsqueeze(1)
elif mask_b1hw_01.ndim == 4 and mask_b1hw_01.shape[1] == 1:
m = mask_b1hw_01
else:
raise ValueError(f"Unexpected mask shape: {tuple(mask_b1hw_01.shape)} (expected B,H,W or B,1,H,W)")
m = m[:1].float()
target_h, target_w = target_cond_hw(latent_h, latent_w, patch_spatial)
if m.shape[-2] != target_h or m.shape[-1] != target_w:
m = F.interpolate(m, size=(target_h, target_w), mode="nearest")
return (m >= 0.5).float()
def build_inpaint_cond_image(rgb_pm1: torch.Tensor, mask01: torch.Tensor, masked_input: bool) -> torch.Tensor:
"""rgb_pm1: (1, 3, H, W) in [-1, 1], mask01: (1, 1, H, W) in {0, 1}. Returns (1, 4, H, W).
The mask channel is rescaled to [-1, +1] (matching the RGB range), and if
``masked_input`` is set the RGB is zeroed where ``mask >= 0.5``.
"""
if masked_input:
keep = (mask01 < 0.5).to(rgb_pm1.dtype)
rgb_pm1 = rgb_pm1 * keep
mask_pm1 = mask01.to(rgb_pm1.dtype) * 2.0 - 1.0
return torch.cat([rgb_pm1, mask_pm1], dim=1)View on GitHub (pinned to 0b6a024f2f)
Solutions
- Pass shape (B,H,W) or (B,1,H,W); squeeze extra channels: mask[:, :1] or mask[:, 0].
- Add the batch dim for a single mask: mask.unsqueeze(0).
- Convert RGB masks to single-channel first (e.g. take luminance or alpha).
- Binarize/normalize values to [0,1] so the >=0.5 threshold behaves as intended.
Example fix
# before m = prepare_mask(mask_rgb, latent_h, latent_w) # (B,3,H,W) -> ValueError # after mask_gray = mask_rgb.mean(dim=1, keepdim=True) # (B,1,H,W) m = prepare_mask(mask_gray, latent_h, latent_w)
Defensive patterns
Strategy: validation
Validate before calling
import torch
def validate_mask(mask: torch.Tensor) -> None:
if not isinstance(mask, torch.Tensor):
raise TypeError("mask must be a torch.Tensor")
ok = mask.ndim == 3 or (mask.ndim == 4 and mask.shape[1] == 1)
if not ok:
raise ValueError(f"expected (B,H,W) or (B,1,H,W), got {tuple(mask.shape)}")
if mask.ndim == 3:
mask = mask.unsqueeze(1)
if mask.min() < 0.0 or mask.max() > 1.0:
raise ValueError("mask values must be in [0,1]") Type guard
def is_mask_b1hw(t) -> bool:
import torch
return isinstance(t, torch.Tensor) and (t.ndim == 3 or (t.ndim == 4 and t.shape[1] == 1)) Try / catch
try:
m = prepare_mask(mask, latent_h, latent_w)
except ValueError as e:
raise ValueError(f"bad mask: {e}; provide (B,H,W) or (B,1,H,W) in [0,1]") from e Prevention
- Never pass the RGB cond image where a mask is expected.
- Reduce RGBA masks to one channel before calling.
- Add unsqueeze(0) for single masks loaded as (H,W).
- Pre-binarize masks if you need a hard edge (function thresholds at 0.5).
When it happens
Trigger: Calling prepare_mask (or _build_lllite_cond_image) with an RGB (B,3,H,W) tensor, a (1,H,W)-only-mask confusion where ndim==4 but channel != 1, a (H,W) 2-D tensor, or a (B,4,H,W) RGBA mask.
Common situations: Passing the cond image where a mask is expected, forgetting unsqueeze(0) on a single (H,W) mask, or loading a multi-channel mask from an RGBA PNG without selecting one channel.
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
- Unexpected cond image shape: {tuple(rgb_bchw_01.shape)} (exp
- LLLite module '{m.lllite_name}' was trained for in_features=
- Latent spatial dims must be even, got {h}x{w}
- The Anima ControlNet-LLLite model '{lllite_field.control_mod
- This Anima ControlNet-LLLite adapter is an inpainting adapte
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/02a1c867bd1b61a5.
Report an issue: GitHub.