Comfy-Org/ComfyUI · error · ValueError

This Controlnet needs a VAE but none was provided, please us

Error message

This Controlnet needs a VAE but none was provided, please use a ControlNetApply node with a VAE input and connect it.

What it means

ControlNet raises this when the loaded controlnet operates in latent space (latent_format is not None, e.g. controlnets that consume VAE-encoded hints like those for Flux/SD3-style latents) but no VAE was wired into the ControlNetApply node. Without the VAE, compression cannot be computed and the hint cannot be encoded, so the error tells you to connect the VAE input.

Source

Thrown at comfy/controlnet.py:278

                if control_prev is not None:
                    return control_prev
                else:
                    return None

        dtype = self.control_model.dtype
        if self.manual_cast_dtype is not None:
            dtype = self.manual_cast_dtype

        if self.cond_hint is None or x_noisy.shape[2] * self.compression_ratio != self.cond_hint.shape[2] or x_noisy.shape[3] * self.compression_ratio != self.cond_hint.shape[3]:
            if self.cond_hint is not None:
                del self.cond_hint
            self.cond_hint = None
            compression_ratio = self.compression_ratio
            if self.vae is not None:
                compression_ratio *= self.vae.spacial_compression_encode()
            else:
                if self.latent_format is not None:
                    raise ValueError("This Controlnet needs a VAE but none was provided, please use a ControlNetApply node with a VAE input and connect it.")
            self.cond_hint = comfy.utils.common_upscale(self.cond_hint_original, x_noisy.shape[-1] * compression_ratio, x_noisy.shape[-2] * compression_ratio, self.upscale_algorithm, "center")
            self.cond_hint = self.preprocess_image(self.cond_hint)
            if self.vae is not None:
                loaded_models = comfy.model_management.loaded_models(only_currently_used=True)
                self.cond_hint = self.vae.encode(self.cond_hint.movedim(1, -1))
                comfy.model_management.load_models_gpu(loaded_models)
            if self.latent_format is not None:
                self.cond_hint = self.latent_format.process_in(self.cond_hint)
            if len(self.extra_concat_orig) > 0:
                to_concat = []
                for c in self.extra_concat_orig:
                    c = c.to(self.cond_hint.device)
                    c = comfy.utils.common_upscale(c, self.cond_hint.shape[-1], self.cond_hint.shape[-2], self.upscale_algorithm, "center")
                    if c.ndim < self.cond_hint.ndim:
                        c = c.unsqueeze(2)
                        c = comfy.utils.repeat_to_batch_size(c, self.cond_hint.shape[2], dim=2)
                    to_concat.append(comfy.utils.repeat_to_batch_size(c, self.cond_hint.shape[0]))
                self.cond_hint = torch.cat([self.cond_hint] + to_concat, dim=1)

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Open the ControlNetApply node and connect the workflow's VAE to its VAE input.
  2. Use ControlNetApplyAdvanced with the VAE input connected for latent-space controlnets.
  3. If the workflow should stay pixel-space, load the pixel-space variant of the controlnet instead.

Example fix

# workflow (dict) before: apply node missing vae link
{"class_type": "ControlNetApplyAdvanced", "inputs": {"positive": [...], "negative": [...], "control_net": [...]}}

# after: add vae input
{"class_type": "ControlNetApplyAdvanced", "inputs": {"positive": [...], "negative": [...], "control_net": [...], "vae": ["4", 0]}}
Defensive patterns

Strategy: validation

Validate before calling

if controlnet.latent_format is not None and vae is None:
    raise SystemExit("connect the VAE input of ControlNetApply for this controlnet")

Type guard

def controlnet_needs_vae(controlnet) -> bool:
    return getattr(controlnet, "latent_format", None) is not None

Try / catch

try:
    cn.apply_model(...)
except ValueError as e:
    if "needs a VAE" in str(e):
        raise SystemExit("wire the VAE into the ControlNetApply node")
    raise

Prevention

When it happens

Trigger: Using ControlNetApply (or ControlNetApplyAdvanced) without linking the positive/negative VAE input while the controlnet model requires latent hints (latent_format set at load time); swapping a pixel-space controlnet for a latent-space one in an existing workflow without adding the VAE link.

Common situations: Newer latent-hint controlnet models dropped into old workflows; converting a workflow that previously didn't need the VAE connection; forgetting that some apply nodes have an optional-but-required-here VAE socket.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/b7d5120e46f98399. Report an issue: GitHub.