Comfy-Org/ComfyUI · error · RuntimeError
Qwen Fun ControlNet requires a control hint image.
Error message
Qwen Fun ControlNet requires a control hint image.
What it means
After resolving the base model, the Qwen Fun ControlNet must convert a control image ('hint') into hint tokens; _process_hint_tokens returns None when no usable hint was passed, and the code raises RuntimeError immediately. The hint is the structural conditioning (depth/pose/canny/etc.) and is mandatory for Fun controlnets.
Source
Thrown at comfy/ldm/qwen_image/controlnet.py:133
attention_mask=None,
guidance: torch.Tensor = None,
hint=None,
transformer_options={},
base_model=None,
**kwargs,
):
if base_model is None:
raise RuntimeError("Qwen Fun ControlNet requires a QwenImage base model at runtime.")
encoder_hidden_states_mask = attention_mask
# Keep attention mask disabled inside Fun control blocks to mirror
# VideoX behavior (they rely on seq lengths for RoPE, not masked attention).
encoder_hidden_states_mask = None
hidden_states, img_ids, _ = base_model.process_img(x)
hint_tokens = self._process_hint_tokens(hint)
if hint_tokens is None:
raise RuntimeError("Qwen Fun ControlNet requires a control hint image.")
if hint_tokens.shape[1] != hidden_states.shape[1]:
max_tokens = min(hint_tokens.shape[1], hidden_states.shape[1])
hint_tokens = hint_tokens[:, :max_tokens]
hidden_states = hidden_states[:, :max_tokens]
img_ids = img_ids[:, :max_tokens]
txt_start = round(
max(
((x.shape[-1] + (base_model.patch_size // 2)) // base_model.patch_size) // 2,
((x.shape[-2] + (base_model.patch_size // 2)) // base_model.patch_size) // 2,
)
)
txt_ids = torch.arange(txt_start, txt_start + context.shape[1], device=x.device).reshape(1, -1, 1).repeat(x.shape[0], 1, 3)
ids = torch.cat((txt_ids, img_ids), dim=1)
image_rotary_emb = base_model.pe_embedder(ids).to(x.dtype).contiguous()
hidden_states = base_model.img_in(hidden_states)View on GitHub (pinned to 1c6d8d45b3)
Solutions
- Connect a control image (or preprocessor output) to the control image input of the Fun ControlNet apply node.
- Un-bypass/unmute any preprocessor nodes feeding the hint.
- Verify the image tensor is non-empty and has the expected CHW/BHWC layout the apply node expects.
- If you did not intend image control, remove the Fun ControlNet from the conditioning chain entirely.
Defensive patterns
Strategy: validation
Validate before calling
def validate_hint(hint):
import torch
if hint is None or (torch.is_tensor(hint) and hint.numel() == 0):
raise ValueError("Fun ControlNet needs a non-empty control image; check preprocessor wiring")
return hint Type guard
def has_control_image(hint) -> bool:
import torch
return torch.is_tensor(hint) and hint.numel() > 0 and hint.dim() >= 3 Prevention
- Connect a preprocessor or load-image node to the control image input before applying the controlnet.
- Bypassed preprocessors pass None — unmute them.
- Smoke-test workflows with a tiny dummy control image before long runs.
When it happens
Trigger: Applying Qwen Fun ControlNet through the proper apply node but leaving the control image input empty; passing hint=None via custom code; the control-image preprocessor node is bypassed so None flows into the apply node.
Common situations: Workflow copied from a text-only example where the image input was never wired; preprocessor (e.g. depth estimator) muted/bypassed; empty image mask or a load-image node pointing at a missing file yielding None.
Related errors
- Control type {max_type_name}({max_type}) is out of range for
- Qwen Fun ControlNet requires a QwenImage base model at runti
- floats_strength must be either an iterable input or a float,
- INVALID_TAG_FILTER
- UNSUPPORTED_MEDIA_TYPE
AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14).
Data as JSON: /api/errors/72cd23966b28e787.
Report an issue: GitHub.