Qwen-Image ControlNet Loader ⚡
One loader for three Qwen-Image ControlNet formats — it figures out which you have
- qwen_control
The annoying thing about Qwen-Image ControlNets is that they're not one thing. There's the InstantX/Union checkpoint, the Qwen-Image-Fun ControlNet, and the DiffSynth canny/depth/inpaint patches - three formats that attach to the model through two completely different ComfyUI mechanisms. Some workflows make you know which one you downloaded and pick the matching loader. This node takes a single control_name dropdown, figures out which mechanism the file needs, and does the right thing. The source calls itself "a dispatcher, not a reimplementation," and that's exactly right.
The two mechanisms it has to juggle
- DiffSynth patches (canny/depth/inpaint - files like
qwen_image_canny_diffsynth_controlnet.safetensors) are aMODEL_PATCH. They attach to the MODEL itself viaDiffSynthCnetPatch. The loader detects these by checking for the one signature that's unique to that format:controlnet_blocks.0.y_rms.weight. - InstantX/Union and Qwen-Image-Fun are both real
ControlNetobjects. They attach to CONDITIONING the way a classic ControlNet does, viacomfy.controlnet.load_controlnet_state_dict(). Fun lands here too - despite the name, it's a genuine ControlNet architecture, and comfy's own dispatcher already recognizes its signature internally. This loader doesn't reimplement any of that; it falls through to core.
So the detection is a single signature check plus a fallthrough - simple, and robust because it leans on ComfyUI core's own code rather than reimplementing detection for each format.
The one input, one output
control_name- picked frommodels/model_patchesormodels/controlnet(the node resolves both folders, so drop your file in whichever one you keep ControlNets in).qwen_control(QWEN_IMAGE_CONTROL) - this is a wrapper type tagging which attachment point the loaded checkpoint needs. It exists because of the two mechanisms: the node tells the downstream img2img node which socket to use, so you never have to know.
Wire qwen_control into Qwen-Image img2img's qwen_control input. The img2img node routes to whichever attachment the checkpoint needs - DiffSynthCnetPatch on a cloned MODEL for patches, or the standard set_cond_hint() conditioning path for InstantX/Union/Fun.
Installing it
Part of the ComfyUI-GGUF-Loader pack under 🤖 CCTech/Qwen-Image. ComfyUI Manager → search "ComfyUI-GGUF-Loader" → install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/ChrisColeTech/ComfyUI-GGUF-Loader
cd ComfyUI-GGUF-Loader
pip install -r requirements.txt
Common issues
The main practical gotcha is preprocessing, which no loader can solve for you: the DiffSynth canny, depth, and inpaint patches each want a different control map, and the file itself doesn't say which preprocessor it needs. That's why Qwen-Image img2img has a control_mode input - manual (you connect control_image yourself), auto_canny, or auto_depth. Pick the mode that matches the checkpoint you loaded. If a canny patch gets a depth map, you'll get edges interpreted as depth, and the output will look wrong in a way that's hard to untangle. And remember: qwen_control with nothing usable to attach raises immediately, but a control_image connected with no qwen_control loaded is just ignored with a warning - so a "silently not controlling anything" workflow is usually the second case.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| control_name | COMBO | An InstantX/Union or Fun ControlNet checkpoint, or a DiffSynth canny/depth/inpaint patch, from models/model_patches or models/controlnet. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| qwen_control | QWEN_IMAGE_CONTROL | — |