invoke-ai/InvokeAI · error · ValueError
InpaintExt should be used only on normal (non-inpainting) mo
Error message
InpaintExt should be used only on normal (non-inpainting) models. This could be caused by an inpainting model that was incorrectly marked as a non-inpainting model. In some cases, this can be fixed by removing and re-adding the model (so that it gets re-probed).
What it means
InpaintExt is the extension for adding mask/source latents to NORMAL (4-channel) UNets by lerping them into the latents. init_tensors asserts the loaded UNet is not an inpainting model (9-channel); if it is, the wrong extension was attached and ValueError is raised. The message also flags likely model-probe misclassification.
Source
Thrown at invokeai/backend/stable_diffusion/extensions/inpaint.py:78
t = einops.repeat(t, "-> batch", batch=batch_size)
# Noise shouldn't be re-randomized between steps here. The multistep schedulers
# get very confused about what is happening from step to step when we do that.
mask_latents = ctx.scheduler.add_noise(ctx.inputs.orig_latents, self._noise, t)
# TODO: Do we need to also apply scheduler.scale_model_input? Or is add_noise appropriately scaled already?
# mask_latents = self.scheduler.scale_model_input(mask_latents, t)
mask_latents = einops.repeat(mask_latents, "b c h w -> (repeat b) c h w", repeat=batch_size)
if self._is_gradient_mask:
threshold = (t.item()) / ctx.scheduler.config.num_train_timesteps
mask_bool = mask < 1 - threshold
masked_input = torch.where(mask_bool, latents, mask_latents)
else:
masked_input = torch.lerp(latents, mask_latents.to(dtype=latents.dtype), mask.to(dtype=latents.dtype))
return masked_input
@callback(ExtensionCallbackType.PRE_DENOISE_LOOP)
def init_tensors(self, ctx: DenoiseContext):
if not self._is_normal_model(ctx.unet):
raise ValueError(
"InpaintExt should be used only on normal (non-inpainting) models. This could be caused by an "
"inpainting model that was incorrectly marked as a non-inpainting model. In some cases, this can be "
"fixed by removing and re-adding the model (so that it gets re-probed)."
)
self._mask = self._mask.to(device=ctx.latents.device, dtype=ctx.latents.dtype)
self._noise = ctx.inputs.noise
# 'noise' might be None if the latents have already been noised (e.g. when running the SDXL refiner).
# We still need noise for inpainting, so we generate it from the seed here.
if self._noise is None:
self._noise = torch.randn(
ctx.latents.shape,
dtype=torch.float32,
device="cpu",
generator=torch.Generator(device="cpu").manual_seed(ctx.seed),
).to(device=ctx.latents.device, dtype=ctx.latents.dtype)
View on GitHub (pinned to 0b6a024f2f)
Solutions
- Remove and re-add the model in the model manager so it is re-probed with the correct variant.
- Verify the checkpoint really is a non-inpainting model and choose the matching inpaint pipeline/extension instead (InpaintModelExt).
- Update InvokeAI in case the variant-probing bug is fixed upstream.
- Check is_inpainting_model(unet) (conv_in.in_channels == 9) before attaching InpaintExt in custom code.
Example fix
// before
extensions.append(InpaintExt(mask, masked_latents)) # unet is inpainting model
// after
if unet.conv_in.in_channels == 9:
extensions.append(InpaintModelExt(mask, masked_latents))
else:
extensions.append(InpaintExt(mask, masked_latents)) Defensive patterns
Strategy: validation
Validate before calling
if unet.conv_in.in_channels == 9:
raise ValueError("InpaintExt cannot be used with an inpainting (9-channel) UNet") Type guard
def is_normal_model(unet) -> bool:
return unet.conv_in.in_channels != 9 Try / catch
try:
result = pipeline(...)
except ValueError as e:
if "InpaintExt should be used only on normal" in str(e):
result = run_with_inpaint_model_ext(pipeline, mask, masked_latents)
else:
raise Prevention
- Check UNet in_channels before choosing inpaint extension
- Re-add misdetected models in the model manager to re-probe variant
- Match extension (InpaintExt vs InpaintModelExt) to checkpoint type
- Keep InvokeAI updated for variant-probing fixes
When it happens
Trigger: A denoise graph attaches InpaintExt while ctx.unet is an inpainting model, usually because the model was incorrectly probed/registered as a non-inpainting checkpoint.
Common situations: Model manager misdetecting an inpainting checkpoint's variant; user selecting the wrong pipeline type in the UI; stale model records after files were replaced with different variants.
Related errors
- Source image required for inpaint mask when inpaint model us
- Source image required for inpaint mask when inpaint model us
- InpaintModelExt should be used only on inpaint models!
- Invalid mode selected
- Unexpected control_input type: ${type(control_input)}
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/92b4041770643824.
Report an issue: GitHub.