ControlAltAI: Union ControlNet Apply
One checkpoint, seven conditions, and defaults that are too hot
- conditioning
- control_net
- image
- vae
- CONDITIONING
- VAE
A "union" ControlNet is one set of weights that learned several conditions at once - canny, depth, pose, tile and friends - and picks which one to act as based on a type index you set. That's the trade of the whole format: less precision per condition than a specialist model, one download instead of seven, and the conditioning is decided at graph level rather than by which file you loaded.
This node is the apply step, with the type selector built into it. You feed it a Flux checkpoint's conditioning, a union ControlNet, a preprocessed control image and a VAE, and it hands back conditioning with the hint baked in.
How it works
The dropdown maps to the integer index the union model expects - canny: 0, tile: 1, depth: 2, blur: 3, pose: 4, gray: 5, low quality: 6 - and the node copies the ControlNet, stamps that index onto it via the control_type extra arg, then walks your conditioning list and attaches a fresh cond-hint per entry: the control image, your strength, and the (start_percent, end_percent) window, with the VAE passed in for encoding. It also chains whatever ControlNet was already on that conditioning, which is how you stack a second union unit (the author's note says two is fine, more than two isn't). The control_apply_to_uncond flag is set to False, so if you're running with CFG the hint stays out of the negative pass.
The pleasing bit: strength of 0 returns your conditioning untouched, as a clean early exit. That makes it a free A/B toggle - set it to 0 and the graph behaves as if the ControlNet weren't there.
Inputs and outputs
Required: conditioning, control_net, image, union_controlnet_type, strength (0–10, default 1), start_percent and end_percent (0–1), vae.
Outputs: CONDITIONING - wire that into your sampler's conditioning input - and a VAE passthrough, which is just the VAE you fed in, so you can chain another union unit or a decode without running a second wire from your loader.
Note there is no preprocessing here. image is what goes into the hint, so it should already be edges, a depth map, a pose render - whatever matches the mode you selected. The author's own list of intended preprocessors is Canny Edge or Tile out of ControlNet Aux, Depth Anything V2 Relative for depth, DWPose for pose, a desaturate for gray, and the raw blurry image for blur and "low quality".
The number one mistake: mismatching node and checkpoint
This node's type list is the Union Pro 1.0 vocabulary. Shakker Labs' current Union Pro 2.0 dropped tile and reshuffled the rest, and the 2026-era unions are narrower still - the community's own count is that the modern ones stop around five conditions plus an inpaint mode, against twelve on the 2024 SDXL union. So check which checkpoint you actually downloaded before you trust the dropdown: pick tile on a model that no longer trains tile and you'll get weak or scrambled conditioning, and it will look like the node is broken.
Second: the defaults are hotter than the author's own recommendation. The docs suggest strength 0.15–0.65 and end_percent 0.2–0.9, while the node ships at strength 1.0 and end 1.0. Modern unions got the same memo - Shakker publishes per-mode weights around 0.7–0.9 (0.7 canny, 0.8 depth, 0.9 pose) because the old 1.0 starting point overcooks them. Start at 0.5 and work down.
Installing it
Part of ussoewwin/ComfyUI-NunchakuFluxLoraStacker (a Nunchaku FLUX LoRA stacker, the Florence-2 suite, a TensorRT CCSR upscaler and the ControlAltAI utility set - a Python 3.13 fork of gseth/ControlAltAI-Nodes, hence the hswq_ prefix). Manager: search ComfyUI-NunchakuFluxLoraStacker. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/ussoewwin/ComfyUI-NunchakuFluxLoraStacker.git
pip install -r requirements.txt
Restart, then drop your union checkpoint into ComfyUI/models/controlnet/ and load it with the stock ControlNetLoader node - it's a normal safetensors ControlNet, and that's where the control_net input comes from. The Shakker/InstantX Flux unions are non-commercial, inheriting the Flux dev licence, so this isn't the graph to build a paid product on.
If something's off
The vae input won't accept your VAE. It must be the Flux VAE that goes with the checkpoint - a mismatch here shows up as garbage conditioning rather than a clean error.
Effects are in the wrong places. Almost always the preprocessor, not the strength. Check the control image in an image preview before you blame the node.
It does nothing at all. Is strength sitting at 0? That's the bypass branch, and it exits silently by design.
Everything from the pack vanished from the menu. Import failure: a requirements.txt package is missing, and the pack's CCSR dependencies are imported up front. Check the console traceback.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| conditioning | CONDITIONING | — | |
| control_net | CONTROL_NET | — | |
| image | IMAGE | — | |
| union_controlnet_type | COMBO | 7 options: canny, tile, depth, blur, pose, gray, +1 | |
| strength | FLOAT | 1.000–10 | — |
| start_percent | FLOAT | 0.0000–1 | — |
| end_percent | FLOAT | 1.0000–1 | — |
| vae | VAE | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| CONDITIONING | CONDITIONING | — |
| VAE | VAE | — |