Route Blocker
A kill switch for one wire, not the whole graph
- any
- any
You know the Ctrl+M gesture: mute a node, and everything behind it stops running while the rest of the graph carries on. It's the fastest way to switch off a branch without deleting it. The catch is that it's a manual, per-node thing, and a muted node doesn't survive a boolean from upstream deciding it should be off.
Route Blocker is that gesture as a node. Drop it inline on any wire, and it becomes the question "does this line run?" - switchable by hand or driven by the graph.
What it is, mechanically
Two required inputs and one optional value in, one value out.
block is the switch. Off, the node is a straight piece of wire: whatever comes in goes out untouched, as if it weren't there. On, the value gets handed to mode.
mode picks which kind of off you want:
emptyreturnsNoneand passes it along. Downstream nodes still execute - they just get an empty value and are expected to cope with it.cutreturns ComfyUI'sExecutionBlocker, the same signal the core uses to skip a branch. Everything behind this node is silently skipped, while other branches in the graph run normally. Structurally identical to muting the branch; the difference is that you didn't rewire anything.
any (optional, wildcard type) is the value being passed or cut. It's optional on purpose: unwired, it's already empty, so emitting an empty value raises nothing and you can prototype the switch before the rest of the graph exists.
Output is a single any, and its type follows whatever you wired in. Passing, it's your original value; blocked, it's either None or a blocking signal.
How this differs from an if/else node
They're often mentioned together and they solve opposite problems. An if/else is pick one of two: two branches arrive, one leaves, and the untaken side doesn't evaluate. Route Blocker is go or no-go on one line: there's no second path, no selector, no choice being made. You just want to stop one wire, in place, without redrawing the graph around it. The plumbing layer has a name for the blocked case - a null-output placeholder, the mechanism for muting a branch from inside the data rather than by bypassing the node.
That distinction is also why you'd reach for this instead of a bypass: bypassing a node makes it pass its input straight to its output, which for a chain of processing nodes can produce garbage. Cutting the line stops the whole downstream chain instead, which is what you usually mean.
Driving it from upstream
block is a normal boolean input, so it takes a wire. Feed it from a comparison, from the pack's bool toggle, or from an Exists node - and the "is there a high-res model loaded, should the refine pass run?" question stops being a manual toggle and becomes graph logic. That combination is the real reason this node exists: Exists answers the question, Route Blocker acts on the answer, and neither of them needed a second branch of plumbing.
Installing it
Manager → Install Custom Nodes → ComfyUI-QG-tools. If that search comes up empty, the clone:
cd ComfyUI/custom_nodes
git clone https://github.com/live1617/ComfyUI-QG-tools
Restart ComfyUI fully and check for QG-tools v0.9.7 | 38 nodes loaded | 8 categories in the console. Nothing to pip install and nothing to download - the pack's requirements.txt is comments only. It lives in QG-tools/Logic.
Worth noting for anyone who's been bitten by node packs breaking under the new frontend: this pack explicitly ports its canvas-drawn nodes to DOM so it behaves the same under Nodes 2.0 and the legacy canvas. That's more than some far more famous packs have managed.
Where people get burned
empty doesn't mean "stop". This is the number one confusion. In empty mode, downstream still runs with None, and anything that genuinely needs the value - a sampler wanting a latent, an upscaler wanting an image - will throw. If your intent is "skip this section", you want cut.
cut fails silently, by design. The skipped nodes produce no error and no output, so a save node that simply never wrote a file looks like a mystery. If a run finishes suspiciously fast and one branch of your graph produced nothing, check whether something upstream of it was cut.
Not every consumer tolerates a None. empty is the right mode when the receiving node has an optional input - the pack's Exists node, for instance, or a combinator that skips empty values. It's the wrong mode in front of anything required.
The switch is a widget until you convert it. block is a boolean widget by default; right-click it and convert it to an input if you want upstream logic to drive it. Nothing about the node changes - it just becomes a socket.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| block | BOOLEAN | false | Off passes the value straight through, as if this node were not on the wire; on hands it to the mode below. You can also wire in an upstream boolean and let the graph decide for itself. |
| mode | COMBO | empty | empty turns the value into None and passes it on, so downstream still runs and handles the empty value itself. cut emits an execution-blocking signal and the nodes behind it are skipped silently, the same as pressing Ctrl+M on this wire, leaving other branches in the graph untouched. |
| anyopt | * | The value to pass or to cut, of any type. Unwired it is already empty, so emitting an empty value raises nothing. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| any | * | The original value when it passes, an empty value or a blocking signal when it is cut. The type follows the input. |