Universal Node Bypass
The A/B switch that doesn't even run the branch you don't pick
- original_1
- processed_1
- original_2
- processed_2
- original_3
- processed_3
- original_4
- processed_4
- original_5
- processed_5
- original_6
- processed_6
- original_7
- processed_7
- original_8
- processed_8
- original_9
- processed_9
- original_10
- processed_10
- original_11
- processed_11
- original_12
- processed_12
- original_13
- processed_13
- original_14
- processed_14
- original_15
- processed_15
- original_16
- processed_16
- output_1
- output_2
- output_3
- output_4
- output_5
- output_6
- output_7
- output_8
- output_9
- output_10
- output_11
- output_12
- output_13
- output_14
- output_15
- output_16
Most "switch" nodes in ComfyUI pick an input and pass it along - but the inputs are all already computed, so the branch you didn't want still ran. Universal Node Bypass is the other kind: a lazy A/B selector that asks ComfyUI to evaluate only the branch it actually uses. Flip it to BYPASS and the processor branch never executes. Flip it to PROCESS and the original branch isn't even requested. For an expensive node - a sampler, an upscaler, a model load - that's real time and VRAM saved on every queue.
It's part of the ComfyUI-H3-Reference-Library pack (a.k.a. ComfyUI-Minimax-H3-Reference-Library), under Skeba AI Nodes - Utilities.
How it works
Each lane is a three-socket set: original_N, processed_N, and output_N. The idea is dead simple:
source -----------------------> original_1
+----> processor ----------> processed_1
Universal Node Bypass output_1 ----> downstream
The single bypass BOOLEAN governs everything. Its default is PROCESS (false), which requests only the processed_N inputs and passes those through. Set it to BYPASS (true) and it requests only the original_N inputs instead. Because the inputs are marked lazy, ComfyUI's executor asks the node which inputs it actually needs before running anything - and the unselected branch is skipped entirely. That's the difference between this and a plain switch.
It scales to sixteen lanes (original_1/processed_1 through original_16/processed_16, with matching output_1..output_16). One empty lane shows initially; connect it and the next appears. Gaps between connected lanes keep their indices across save/reload, and unused trailing lanes stay hidden.
Two behaviors worth internalizing:
- All three sockets in a lane must share a type. The node is type-agnostic (
*), and lanes adopt the type of their first connection - but original, processed, and output have to agree. A type-changing processor needs anoriginal_Nthat matches its output type; you can't bypass an IMAGE straight into a LATENT lane. - The lazy skip only works if this node is the processor's only consumer. If anything else also reads that processor's result, the processor runs anyway. The node's README is blunt about this, and it's the one thing that makes people think the bypass is broken.
Where it fits
Any spot where you flip between "do the thing" and "skip the thing" and you don't want the skipped path costing you. The canonical example: a detail pass or upscaler you sometimes want, sometimes don't. Keep the raw frames on original_1, the processed result on processed_1, and flip one boolean instead of muting a node or rewiring. It's the grown-up version of the simple Skeba Bypass, which passes through but always outputs None when off and can't skip an entire upstream branch.
Installing it
ComfyUI Manager - search "Skeba" or "H3-Reference-Library" - or:
cd ComfyUI/custom_nodes
git clone https://github.com/nikaskeba/ComfyUI-H3-Reference-Library
Restart ComfyUI. No extra dependencies, no model files.
Where people get burned
- The unselected branch still runs if something else reads it. The lazy contract is "only this switch consumes it." Shared connections defeat it - check before assuming the bypass saved you anything.
- A selected input that's missing is a loud error, and a good one: it names the lane and the exact socket you must connect. Read it, wire it, done.
- Type mismatches fail. Image-in / latent-lane isn't a bypass, it's a conversion - use the right sockets or an explicit conversion node.
- This is a utility, not a model. No weights, no downloads, nothing to tune. If you find yourself fighting it, the fight is usually about which branch owns the value, not the node itself.
Inputs (33)
| Name | Type | Default | Description |
|---|---|---|---|
| bypass | BOOLEAN | false | — |
| original_1opt | * | — | |
| processed_1opt | * | — | |
| original_2opt | * | — | |
| processed_2opt | * | — | |
| original_3opt | * | — | |
| processed_3opt | * | — | |
| original_4opt | * | — | |
| processed_4opt | * | — | |
| original_5opt | * | — | |
| processed_5opt | * | — | |
| original_6opt | * | — | |
| processed_6opt | * | — | |
| original_7opt | * | — | |
| processed_7opt | * | — | |
| original_8opt | * | — | |
| processed_8opt | * | — | |
| original_9opt | * | — | |
| processed_9opt | * | — | |
| original_10opt | * | — | |
| processed_10opt | * | — | |
| original_11opt | * | — | |
| processed_11opt | * | — | |
| original_12opt | * | — | |
| processed_12opt | * | — | |
| original_13opt | * | — | |
| processed_13opt | * | — | |
| original_14opt | * | — | |
| processed_14opt | * | — | |
| original_15opt | * | — | |
| processed_15opt | * | — | |
| original_16opt | * | — | |
| processed_16opt | * | — |
Outputs (16)
| Name | Type | Description |
|---|---|---|
| output_1 | * | — |
| output_2 | * | — |
| output_3 | * | — |
| output_4 | * | — |
| output_5 | * | — |
| output_6 | * | — |
| output_7 | * | — |
| output_8 | * | — |
| output_9 | * | — |
| output_10 | * | — |
| output_11 | * | — |
| output_12 | * | — |
| output_13 | * | — |
| output_14 | * | — |
| output_15 | * | — |
| output_16 | * | — |