Nodes/comfyui-obvpm/Optional Any (obvpm)
ComfyUI Node

Optional Any (obvpm)

The gate that lets a socket stay empty

By chanon·Created about a month ago·Updated a day ago· 42
Optional Any (obvpm)
  • input
  • value
  • present
on_emptymute

Most ComfyUI errors you'll fight this month are not model problems. They're a socket with nothing wired into it. You unplug the ControlNet you didn't need, or the reference image that only exists for half your renders, and the graph refuses to queue because something three hops downstream declared that input required.

Optional Any (obvpm) is a one-wire decision point for that exact situation: is there a value here, and if not, what should the rest of the graph do about it?

What it's actually for

It's the wildcard member of a family - Optional Image, Optional Video, Optional Audio, Optional Latent, Optional Any. The typed versions exist so a graph doesn't have to silently accept garbage on a typed socket; this one takes anything, which is what you want when the thing travelling down the wire is a conditioning dict, a bounding box, or a string you invented.

The interesting half isn't passing the value through. It's the on_empty decision, which is where most people's mental model of ComfyUI breaks.

Mute and bypass are not the same thing

ComfyUI gives you two ways to say "nothing here", and they bite differently:

  • mute pushes an ExecutionBlocker out of the value socket. Every node downstream of it is skipped silently, and nothing downstream can catch or handle the absence. It's a kill switch, not a signal.
  • bypass forwards None. A downstream node with an optional input reads that as "unconnected" and does whatever it does about it. Feed that same None into a required input and you get an error - the tolerant path only works if the consumer is tolerant.

So mute is for "this whole branch is dead today", and bypass is for "let the consumer decide". Neither one stops the work happening upstream of the gate; by the time the gate can object, whatever fed it already ran. That distinction is the single most useful thing to internalise about this node family.

The two fields on the node

There isn't much to configure. on_empty is a two-value toggle - mute or bypass, defaulting to mute - and its tooltip is the author's own: mute skips every downstream node, bypass outputs None. input is the optional * socket you plug into; leave it unconnected and the gate does its thing.

The outputs are value (the input, or blocked / None per the toggle) and present, a BOOLEAN. present is the clever bit: it reports whether something is connected, and it stays live even in mute mode, because the blocker only sits on the value socket. That means a muted branch can still tell the rest of the graph "I have nothing" without killing the decision logic.

The pattern that unlocks: wire present into a Lazy Switch's boolean, and the switch will skip the whole unselected side's upstream work instead of just blocking the nodes after it. Gate stops the downstream half, Laziness stops the upstream half. Together they switch a branch off completely - and it's genuinely easy to misdiagnose which half you're missing, because a muted branch looks identical to a running one on the canvas.

Install

ComfyUI Manager, search comfyui-obvpm (the pack title), or:

cd ComfyUI/custom_nodes
git clone https://github.com/chanon/comfyui-obvpm

Restart ComfyUI. No extra Python dependencies - the pack's pyproject.toml deliberately declares none, since torch, numpy and friends are already in ComfyUI's own requirements. Every node in the pack has (obvpm) on the end of its class id, so searching the node menu for obvpm finds all of them; that suffix landed in 0.2.0 to stop the pack's Bundle id clashing with another pack's, and older workflows get migrated automatically when you open them.

Where people get burned

Muting a path you still want to count is the classic. present exists so you don't have to: keep the flag live, use it as a condition, and let a Lazy Switch decide what actually runs. Second one - bypass into a required input throws, which reads like a bug and isn't. If the downstream node's input is required, the branch has to be muted, or the consumer has to be a node that tolerates None.

Categoryobvpm/gates

Inputs (2)

NameTypeDefaultDescription
on_emptyCOMBOmuteWhat downstream sees when no input is connected: mute skips every downstream node, bypass outputs None.
inputopt*The value to pass through. May be left unconnected.

Outputs (2)

NameTypeDescription
value*The input passed through. When the input is empty: blocked (mute) or None (bypass).
presentBOOLEANTrue when an input is connected. Stays live even in mute mode.