Comfy-Org/ComfyUI · error · Exception
Mask and Image must be the same size
Error message
Mask and Image must be the same size
What it means
Thrown by the Dall-E 2 image-edit path in nodes_openai.py when the supplied mask tensor's spatial dimensions do not match the input image's. The RGBA edit payload is built from the image and the mask is written into its alpha channel, so mismatched sizes would corrupt the payload. Checked as mask.shape[1:] != image.shape[1:-1].
Source
Thrown at comfy_api_nodes/nodes_openai.py:219
validate_string(prompt, strip_whitespace=False)
model = "dall-e-2"
path = "/proxy/openai/images/generations"
content_type = "application/json"
request_class = OpenAIImageGenerationRequest
img_binary = None
if image is not None and mask is not None:
path = "/proxy/openai/images/edits"
content_type = "multipart/form-data"
request_class = OpenAIImageEditRequest
input_tensor = image.squeeze().cpu()
height, width, channels = input_tensor.shape
rgba_tensor = torch.ones(height, width, 4, device="cpu")
rgba_tensor[:, :, :channels] = input_tensor
if mask.shape[1:] != image.shape[1:-1]:
raise Exception("Mask and Image must be the same size")
rgba_tensor[:, :, 3] = 1 - mask.squeeze().cpu()
rgba_tensor = downscale_image_tensor(rgba_tensor.unsqueeze(0)).squeeze()
image_np = (rgba_tensor.numpy() * 255).astype(np.uint8)
img = Image.fromarray(image_np)
img_byte_arr = BytesIO()
img.save(img_byte_arr, format="PNG")
img_byte_arr.seek(0)
img_binary = img_byte_arr # .getvalue()
img_binary.name = "image.png"
elif image is not None or mask is not None:
raise Exception("Dall-E 2 image editing requires an image AND a mask")
response = await sync_op(
cls,
ApiEndpoint(path=path, method="POST"),
response_model=OpenAIImageGenerationResponse,View on GitHub (pinned to 1c6d8d45b3)
Solutions
- Resize the mask to exactly the image's HxW before connecting it (e.g. a resize node matching the image)
- Load the mask from the same LoadImage node output so dimensions stay coupled
- Verify shapes: mask.shape[1:] == image.shape[1:-1] before the edit call
- If the mask must come from elsewhere, generate it from the image itself (e.g. MaskEditor) so it inherits size
Example fix
// before image # (1, 1024, 1024, 3) mask # (1, 512, 512) // after import torch mask = torch.nn.functional.interpolate(mask.unsqueeze(1).float(), size=image.shape[1:3], mode='nearest').squeeze(1)
Defensive patterns
Strategy: validation
Validate before calling
assert mask.shape[1:] == image.shape[1:-1], f"mask {tuple(mask.shape)} != image {tuple(image.shape)}" Type guard
def mask_matches_image(mask, image) -> bool:
return mask.shape[1:] == image.shape[1:-1] Prevention
- Always derive masks from the same LoadImage as the image
- Resize mask and image together when changing resolution
- Assert shape equality in a small check node before the edit node
When it happens
Trigger: Calling OpenAIImageEdit (Dall-E 2 path) with a mask loaded at a different resolution than the image (e.g. 512x512 image with a 1024x1024 mask), or masks coming from a different workflow branch.
Common situations: Loading a mask PNG exported at another size; using an upscaled/downscaled image while keeping the original mask; forgetting that LoadImage returns the mask at the image file's own resolution.
Related errors
- Dall-E 2 image editing requires an image AND a mask
- Cannot use a mask without an input image
- Cannot use a mask with multiple image
- Got a mask of shape {list(mask.shape)}, expected [b, q, k] o
- Custom alpha video frame count ({mask.shape[0]}) does not ma
AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14).
Data as JSON: /api/errors/a3338a9c174db982.
Report an issue: GitHub.