Nodes/qwen-image-controlnets-comfyui/Qwen Image Blockwise ControlNet Loader
ComfyUI Node

Qwen Image Blockwise ControlNet Loader

Where Qwen's blockwise ControlNet weights actually go

By krigeta·Created about a year ago·Updated about a year ago· 2
Qwen Image Blockwise ControlNet Loader
    • QWEN_BLOCKWISE_CONTROLNET
    controlnet_name

    Qwen Image's first controlnets weren't like the SD-era ones. Instead of copying a chunk of the network, DiffSynth-Studio's "blockwise" design injects a small module into each of the model's 60 transformer blocks - that's the "blockwise" in the name. This node loads one of those controlnet files from disk and hands it to the Apply node. It's the Loader half of the pair, and it's mostly a thin wrapper around a few hardcoded numbers.

    The interface

    • controlnet_name - a dropdown that lists whatever .safetensors files sit in your ComfyUI/models/controlnet folder. No file, no dropdown, no download: this loader fetches nothing. The pack's README is nearly empty (it's a "let's test this" repo from August 2025), so the weights come from you.
    • Output - QWEN_BLOCKWISE_CONTROLNET, which plugs straight into QwenImageBlockwiseControlNetApply.

    Where do you get the weights? DiffSynth-Studio published Qwen-Image-Blockwise-ControlNet-Canny, -Depth, and -Inpaint on ModelScope within days of Qwen Image itself launching, and those are the files this loader was written for. Grab the .safetensors, drop it into models/controlnet, restart ComfyUI, and it'll show up in the dropdown.

    How it loads

    The loader builds the architecture from DiffSynth's spec with the dimensions hardcoded: 60 layers, a 3072-wide hidden dimension (that's Qwen-Image's MMDiT shape), and a 64-wide input projection for the conditioning image. It loads the state dict with strict=False, which means mismatched shapes don't crash - they print warnings to your ComfyUI console instead. It then moves the module to your GPU and puts it in eval mode.

    One nice detail straight from the ControlNet playbook: the per-block modules zero-initialize their output projection, so a freshly loaded controlnet starts as an identity and only steers once the weights say to. That's why these things can be added into a frozen model without wrecking it.

    Gotchas

    • Watch the console. "Missing keys in Qwen blockwise controlnet" or "Unexpected keys" printed at load time means the file you grabbed doesn't match the hardcoded 60/64/3072 architecture. It won't error out - it'll just silently not do what you want.
    • Loading success ≠ working controlnet. As written, the Apply node in this pack stores the module you loaded but never actually forwards it into the sampling call - it passes your image and strength to the DiffSynth pipe and lets the pipe handle the rest. So don't treat a clean load as proof the controlnet is influencing output. Test with a real generation.
    • It's a fragment. For the blockwise path to function end-to-end you also need the Apply node and the DiffSynth pipe it wraps (that pipe type lives in a different custom node, not this pack). See the Apply article for the full picture.

    Installing

    Standard: search "qwen-image-controlnets-comfyui" in ComfyUI Manager, or

    cd ComfyUI/custom_nodes
    git clone https://github.com/krigeta/qwen-image-controlnets-comfyui
    cd qwen-image-controlnets-comfyui
    pip install -r requirements.txt
    

    then restart. requirements.txt pulls diffsynth, einops, and opencv-python. And a fair warning: the 20B Qwen model plus a blockwise controlnet is a lot of VRAM, so check your card before you commit to the whole DiffSynth stack.

    CategoryQwen Image/ControlNet

    Inputs (1)

    NameTypeDefaultDescription
    controlnet_nameCOMBO0 options:

    Outputs (1)

    NameTypeDescription
    QWEN_BLOCKWISE_CONTROLNETQWEN_BLOCKWISE_CONTROLNET