Nodes/CMK Flow/CMK ZIT ControlNet Bypass Gate
ComfyUI Node

CMK ZIT ControlNet Bypass Gate

The switch that means an unused ControlNet branch costs nothing

By CMKFlow·Created 3 months ago·Updated 2 days ago· 6
CMK ZIT ControlNet Bypass Gate
  • PROCESS BYPASS
  • IMAGE BYPASS
  • LOG BYPASS
  • PROCESS ACTIVE
  • IMAGE ACTIVE
  • LOG ACTIVE
  • DIAGNOSTIC ACTIVE
  • PROCESS
  • IMAGE
  • LOG
  • diagnostic
◄ENABLEfalse►

A ControlNet in ComfyUI is normally a switch you bolt onto a graph and then forget to remove. Leave it wired up and disabled and you've still got the preprocessor sitting in the path, still got the extra model loaded, still paying for it. CMK's bypass gates exist to make "off" mean off. The ZIT variant is CMK ZIT ControlNet Bypass Gate.

Category is CMK/Developer/Boundary & Cache and it's flagged DEV_ONLY - this is architecture you'll find inside packaged CMK subgraphs. Reading it is still worth it, because it's the clearest example in the pack of lazy evaluation doing real work.

How it works

The node has exactly one real input: ENABLE. Everything else comes in pairs, a … BYPASS set and a … ACTIVE set, and ENABLE decides which pair gets returned.

So the node doesn't "disable" a branch - it selects between two parallel branches that both exist in the graph. When ControlNet is on, the ACTIVE wires (which come through the ControlNet prepare module) win. When it's off, the BYPASS wires - the untouched process, image and log straight from upstream - pass through instead.

The important part is that this selection happens lazily, and the lazy check is written to match the switch:

prefix = "ACTIVE" if bool(ENABLE) else "BYPASS"
for name in (f"PROCESS {prefix}", f"LOG {prefix}"):
    if inputs.get(name) is None:
        return [name]

Only the selected side is ever requested from ComfyUI. The other side's PROCESS and LOG are never evaluated, which means the ControlNet preparation - image scaling, canny, model patch selection - never runs when the gate is off. That's the difference between a bypass gate and a muted wire.

Two details worth knowing:

  • It checks PROCESS and LOG, not IMAGE. The comment in the source explains why: an image may legitimately be None in Text2Image, so PROCESS and LOG are the authoritative evidence that the selected branch actually got evaluated.
  • The diagnostic is only propagated on the active path. With ENABLE off, the diagnostic output is an ExecutionBlocker - nothing to report because nothing ran. With it on, a missing diagnostic is a hard error rather than a silent None.

If the selected branch is missing its PROCESS or LOG, you get a clear "is missing the BYPASS/ACTIVE result" error naming which side failed. That's a good deal more useful than the usual downstream explosion.

Inputs and outputs

  • ENABLE (BOOLEAN, default off) - the switch. Defaults off, which is the safe default: a freshly dropped gate does nothing.
  • PROCESS BYPASS / PROCESS ACTIVE (CMK_PROCESS_Z_IMAGE, lazy) - note these are typed for Z-Image specifically; the SDXL gate is a separate node for a reason.
  • IMAGE BYPASS / IMAGE ACTIVE (IMAGE, lazy)
  • LOG BYPASS / LOG ACTIVE (CMK_LOG_PIPE, lazy)
  • DIAGNOSTIC ACTIVE (CMK_DIAGNOSTIC, lazy)

Outputs: PROCESS (CMK_PROCESS_Z_IMAGE), IMAGE, LOG, diagnostic - the chosen branch's values, straight through.

There's a combined SDXL+ZIT version of the same idea (CMK Combined ControlNet Bypass Gate) for graphs running both families; it selects across both typed pairs at once.

Install

Ships with the pack. Manager → search CMK Flow → install → restart, or:

cd ComfyUI/custom_nodes
git clone https://github.com/CMKFlow/cmk_nodes
python3 custom_nodes/cmk_nodes/scripts/install_cmk_requirements.py

The ZIT ControlNet path needs Z-Image-Turbo-Fun-Controlnet-Union.safetensors - the Alibaba PAI Fun union, which is the well-served Apache 2.0 ControlNet family for Z-Image. The resource checker will tell you whether it's present:

python3 custom_nodes/cmk_nodes/scripts/check_cmk_resources.py --models-root "/path/to/shared/models"

Common issues

  • ENABLE on and an error about the ACTIVE result. The active branch isn't wired or produced nothing - usually a missing ControlNet module or its own disabled state. Enable the module too; the gate selects, it doesn't generate.
  • ENABLE off and ControlNet still seems to affect the image. Check what's feeding the BYPASS PROCESS. If the prepare module mutates the pipe upstream of the gate, both sides carry the change.
  • Wrong gate type. Wiring an SDXL process pipe into this node raises a type error. Use the SDXL gate or the combined one.
  • Type mismatches on the bypass side. Easy to hit when hand-editing: the bypass pair has to be the unprocessed process, image and log from before the ControlNet module, not its outputs.
CategoryCMK/Developer/Legacy Gates

Inputs (8)

NameTypeDefaultDescription
ENABLEBOOLEANfalse—
PROCESS BYPASSoptCMK_PROCESS_Z_IMAGE—
IMAGE BYPASSoptIMAGE—
LOG BYPASSoptCMK_LOG_PIPE—
PROCESS ACTIVEoptCMK_PROCESS_Z_IMAGE—
IMAGE ACTIVEoptIMAGE—
LOG ACTIVEoptCMK_LOG_PIPE—
DIAGNOSTIC ACTIVEoptCMK_DIAGNOSTIC—

Outputs (4)

NameTypeDescription
PROCESSCMK_PROCESS_Z_IMAGE—
IMAGEIMAGE—
LOGCMK_LOG_PIPE—
diagnosticCMK_DIAGNOSTIC—