{"record":{"id":"375027035c9a0b22","repo":"invoke-ai/InvokeAI","slug":"unsupported-mask-shape-mask-shape-expected-1","errorCode":null,"errorMessage":"Unsupported mask shape: {mask.shape}. Expected (1, h, w) or (h, w).","messagePattern":"Unsupported mask shape: (.+?)\\. Expected \\(1, h, w\\) or \\(h, w\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/util/mask.py","lineNumber":19,"sourceCode":"import torch\n\n\ndef to_standard_mask_dim(mask: torch.Tensor) -> torch.Tensor:\n    \"\"\"Standardize the dimensions of a mask tensor.\n\n    Args:\n        mask (torch.Tensor): A mask tensor. The shape can be (1, h, w) or (h, w).\n\n    Returns:\n        torch.Tensor: The output mask tensor. The shape is (1, h, w).\n    \"\"\"\n    # Get the mask height and width.\n    if mask.ndim == 2:\n        mask = mask.unsqueeze(0)\n    elif mask.ndim == 3 and mask.shape[0] == 1:\n        pass\n    else:\n        raise ValueError(f\"Unsupported mask shape: {mask.shape}. Expected (1, h, w) or (h, w).\")\n\n    return mask\n\n\ndef to_standard_float_mask(mask: torch.Tensor, out_dtype: torch.dtype) -> torch.Tensor:\n    \"\"\"Standardize the format of a mask tensor.\n\n    Args:\n        mask (torch.Tensor): A mask tensor. The dtype can be any bool, float, or int type. The shape must be (1, h, w)\n            or (h, w).\n\n        out_dtype (torch.dtype): The dtype of the output mask tensor. Must be a float type.\n\n    Returns:\n        torch.Tensor: The output mask tensor. The dtype is out_dtype. The shape is (1, h, w). All values are either 0.0\n            or 1.0.\n    \"\"\"\n","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/util/mask.py#L1-L37","documentation":"to_standard_mask_dim normalizes a torch mask tensor to shape (1, h, w). It accepts a 2D (h, w) tensor or a 3D tensor whose first dim is exactly 1; anything else (e.g. (3, h, w), (b, 1, h, w), 4D tensors) triggers this ValueError. It exists to guarantee downstream regional-prompt masking code sees a uniform shape.","triggerScenarios":"Passing a mask with 4+ dims (batched), a 3-channel mask shaped (3, h, w) (e.g. an RGB mask image loaded without grayscale conversion), or a (n, h, w) stack with n > 1.","commonSituations":"Loading a mask PNG in RGB mode instead of 'L' mode, forgetting to squeeze a batch dimension after a dataloader/model, stacking multiple regional masks into one tensor.","solutions":["Convert multi-channel masks to single channel: load with PIL Image.open(...).convert('L') or mask = mask.mean(dim=0) / mask[0].","Squeeze or select the batch dim before calling: mask = mask.squeeze(1) or mask = mask[0].","Call to_standard_float_mask with a (h, w) or (1, h, w) tensor only; loop over batch items otherwise."],"exampleFix":"// before\nmask = torch.stack([m1, m2])  # (2, h, w)\nprocess(mask)\n// after\nfor m in [m1, m2]:\n    process(to_standard_float_mask(m, torch.float32))","handlingStrategy":"type-guard","validationCode":"def ensure_mask_shape(mask: torch.Tensor) -> torch.Tensor:\n    if mask.ndim == 3 and mask.shape[0] not in (1,):\n        mask = mask.mean(dim=0, keepdim=False)  # RGB -> single channel\n    if mask.ndim > 3:\n        raise ValueError(f\"mask must be (h,w) or (1,h,w), got {tuple(mask.shape)}\")\n    return mask","typeGuard":"def is_standard_mask(mask: torch.Tensor) -> bool:\n    return mask.ndim == 2 or (mask.ndim == 3 and mask.shape[0] == 1)","tryCatchPattern":"try:\n    m = to_standard_float_mask(mask, torch.float32)\nexcept ValueError as e:\n    if \"Unsupported mask shape\" in str(e):\n        m = to_standard_float_mask(mask.mean(dim=0) if mask.ndim == 3 else mask[0], torch.float32)","preventionTips":["Load mask images with PIL convert('L') so they are single-channel.","Squeeze batch dims before passing masks to regional-prompt APIs.","Keep one mask per tensor; never stack multiple regional masks."],"tags":["python","pytorch","tensor-shape","mask"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}