invoke-ai/InvokeAI · error · ValueError

Source image required for inpaint mask when inpaint model us

Error message

Source image required for inpaint mask when inpaint model used!

What it means

InpaintModelExt's constructor accepts an optional mask, but an inpainting UNet needs both the mask AND the latents of the masked source image to fill its extra 4 input channels. If a mask is given without masked_latents, the extension cannot compute its inputs and raises ValueError in __init__.

Source

Thrown at invokeai/backend/stable_diffusion/extensions/inpaint_model.py:39

        self,
        mask: Optional[torch.Tensor],
        masked_latents: Optional[torch.Tensor],
        is_gradient_mask: bool,
    ):
        """Initialize InpaintModelExt.
        Args:
            mask (Optional[torch.Tensor]): The inpainting mask. Shape: (1, 1, latent_height, latent_width). Values are
                expected to be in the range [0, 1]. A value of 1 means that the corresponding 'pixel' should not be
                inpainted.
            masked_latents (Optional[torch.Tensor]): Latents of initial image, with masked out by black color inpainted area.
                If mask provided, then too should be provided. Shape: (1, 1, latent_height, latent_width)
            is_gradient_mask (bool): If True, mask is interpreted as a gradient mask meaning that the mask values range
                from 0 to 1. If False, mask is interpreted as binary mask meaning that the mask values are either 0 or
                1.
        """
        super().__init__()
        if mask is not None and masked_latents is None:
            raise ValueError("Source image required for inpaint mask when inpaint model used!")

        # Inverse mask, because inpaint models treat mask as: 0 - remain same, 1 - inpaint
        self._mask = None
        if mask is not None:
            self._mask = 1 - mask
        self._masked_latents = masked_latents
        self._is_gradient_mask = is_gradient_mask

    @staticmethod
    def _is_inpaint_model(unet: UNet2DConditionModel):
        """Checks if the provided UNet belongs to a regular model.
        The `in_channels` of a UNet vary depending on model type:
        - normal - 4
        - depth - 5
        - inpaint - 9
        """
        return unet.conv_in.in_channels == 9

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Always pass masked_latents (VAE-encoded masked source image) alongside the mask.
  2. Encode a blank/empty source image if no real source exists, producing valid masked_latents.
  3. If inpainting is not intended, pass mask=None so the extension defaults to a global mask.
  4. Fix the calling code so it never constructs the extension with a mask-only payload.

Example fix

// before
ext = InpaintModelExt(mask=mask, masked_latents=None)
// after
masked_image_latents = vae.encode(source_image * (1 - mask))
ext = InpaintModelExt(mask=mask, masked_latents=masked_image_latents)
Defensive patterns

Strategy: validation

Validate before calling

if mask is not None and masked_latents is None:
    raise ValueError("masked_latents must be provided together with mask")

Type guard

def is_valid_inpaint_ext_args(mask, masked_latents) -> bool:
    return mask is None or masked_latents is not None

Try / catch

try:
    ext = InpaintModelExt(mask=mask, masked_latents=masked_latents)
except ValueError:
    ext = InpaintModelExt(mask=None, masked_latents=None)  # global-mask fallback

Prevention

When it happens

Trigger: Constructing InpaintModelExt(mask=mask, masked_latents=None) — any call where mask is not None but masked_latents is None.

Common situations: Inpaint jobs where the source image was missing or failed to encode; callers building the extension manually with only a mask; UI/API flows that allow mask upload without an image.

Related errors


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