invoke-ai/InvokeAI · error · ValueError

VAE is required when using Z-Image Control. Connect a VAE to

Error message

VAE is required when using Z-Image Control. Connect a VAE to the 'vae' input.

What it means

When a Z-Image ControlNet extension is active, the control image must be VAE-encoded into latent space, which requires a VAE model. If self.vae is None while a control network is configured, _run_diffusion raises ValueError telling the user to connect a VAE to the 'vae' input.

Source

Thrown at invokeai/app/invocations/z_image_denoise.py:472

                control_model_info = context.models.load(self.control.control_model)
                (_, control_adapter) = exit_stack.enter_context(control_model_info.model_on_device())
                assert isinstance(control_adapter, ZImageControlAdapter)

                # Get control_in_dim from adapter config (16 for V1, 33 for V2.0)
                adapter_config = control_adapter.config
                control_in_dim = adapter_config.get("control_in_dim", 16)
                num_control_blocks = adapter_config.get("num_control_blocks", 6)

                # Log control configuration for debugging
                version = "V2.0" if control_in_dim > 16 else "V1"
                context.util.signal_progress(
                    f"Using Z-Image ControlNet {version} (Extension): control_in_dim={control_in_dim}, "
                    f"num_blocks={num_control_blocks}, scale={self.control.control_context_scale}"
                )

                # Load and prepare control image - must be VAE-encoded!
                if self.vae is None:
                    raise ValueError("VAE is required when using Z-Image Control. Connect a VAE to the 'vae' input.")

                control_image = context.images.get_pil(self.control.image_name)

                # Resize control image to match output dimensions
                control_image = control_image.convert("RGB")
                control_image = control_image.resize((self.width, self.height), Image.Resampling.LANCZOS)

                # Convert to tensor format for VAE encoding
                from invokeai.backend.stable_diffusion.diffusers_pipeline import image_resized_to_grid_as_tensor

                control_image_tensor = image_resized_to_grid_as_tensor(control_image)
                if control_image_tensor.dim() == 3:
                    control_image_tensor = einops.rearrange(control_image_tensor, "c h w -> 1 c h w")

                # Encode control image through VAE to get latents
                vae_info = context.models.load(self.vae.vae)
                control_latents = ZImageImageToLatentsInvocation.vae_encode(
                    vae_info=vae_info,

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Connect a VAE model to the denoise invocation's 'vae' input
  2. Use the same VAE as the rest of the pipeline to keep latent spaces consistent
  3. Validate the graph: any control-connected denoise node must also have a VAE connection

Example fix

// before
denoise = ZImageDenoiseInvocation(control=controlnet, vae=None, ...)
// after
denoise = ZImageDenoiseInvocation(control=controlnet, vae=vae_model_field, ...)
Defensive patterns

Strategy: validation

Validate before calling

if denoise.control is not None and denoise.vae is None:
    raise ValueError("ControlNet-connected Z-Image denoise requires a VAE on the 'vae' input")

Try / catch

try:
    output = denoise.invoke(context)
except ValueError as e:
    if "VAE is required" in str(e):
        raise GraphConfigError("connect a VAE node to the denoise 'vae' input") from e
    raise

Prevention

When it happens

Trigger: invoke() on the Z-Image denoise invocation with a connected ControlNet (self.control set) but the 'vae' input left unconnected, so self.vae is None when the control image is prepared.

Common situations: Building a ControlNet workflow and forgetting the VAE connection; copying a denoise node from a non-control workflow; a workflow import that dropped the VAE edge.

Related errors


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