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

Optional Image (obvpm)

The img2img input you don't have to fill in

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

If you've ever built one workflow that does both txt2img and img2img, you've met the problem this node solves. The VAE Encode at the front of the img2img path wants an IMAGE, and there isn't one when you're generating from scratch. So you either maintain two workflows, or you paste a throwaway image into a Load Image node and try to remember to ignore it.

Optional Image (obvpm) turns that hard requirement into a decision. Wire an image in and it passes straight through. Leave it unwired, and on_empty says what the rest of the graph should see - a dead path, or a polite None.

The mechanism, which is the whole story

on_empty has two values:

  • mute (default) - the node emits an ExecutionBlocker on its image output. Every node downstream is skipped, silently. Nothing downstream can catch it; it's a kill, not a message.
  • bypass - the node outputs None. A downstream node whose input is optional reads that as "unconnected" and handles it. A downstream node whose input is required errors on it. So bypass only works when the consumer is written to tolerate absence.

Both modes affect the nodes after the gate only. Whatever fed the gate has already run - the gate can't un-run work. For the img2img case that's usually fine (the Load Image is cheap), but it's the distinction that makes the Lazy Switch family worth having.

Inputs and outputs

  • input - optional IMAGE. The thing to pass through; may be left unconnected.
  • on_empty - mute or bypass.
  • image - the input passed through, or blocked / None when empty.
  • present - BOOLEAN, true when an input is connected, and live even in mute mode, because the blocker only sits on the image socket.

present is the reason this node is more than a guard clause. Convert a downstream KSampler's denoise widget to an input, and you can switch between "txt2img, denoise 1.0" and "img2img, denoise 0.6" based on whether an image exists - feed present through a Lazy Switch and only the chosen side executes. That's the difference between a workflow with two modes and two workflows.

Practical shapes

  • One graph, two modes. Load Image → Optional Image → VAE Encode, with the txt2img path tapping in before the encode. Unplug the image and the img2img half dies on its own; plug one in and it lives.
  • A reference image that's sometimes there. Reference-only ControlNet, IP-Adapter, a style reference - all of them take an IMAGE that isn't always wanted. Gate it, and present drives the branch that switches reference conditioning in and out.
  • Multi-reference workflows. If the second and third references are optional, three gates and three present flags describe the state of your inputs in one place, which is much easier to read than three parallel image chains you toggle by hand.

Install

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

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

Restart ComfyUI. It lands under obvpm/gates, and the node menu search for obvpm lists every node in the pack. No Python dependencies, no downloads - the pack's pyproject.toml declares none on purpose, since everything it imports already ships with ComfyUI. All class ids picked up the (obvpm) suffix in 0.2.0 to avoid colliding with another pack's ids; workflows from before that open fine, since the pack migrates the old names.

Where people get burned

Mute hides the failure, not the cause. A muted branch produces no error and no output - nodes simply don't appear in the run. If an image never reaches your VAE Encode, check whether a gate upstream is in mute before you go hunting in the sampler. Flipping it to bypass usually turns the mystery into a legible error.

Bypass into a required input throws. This is the single most common "the node is broken" report for any gate pack. It isn't broken: bypass means "I'm passing nothing", and a required socket has no way to represent nothing. If the consumer insists, the branch has to be muted. Or use a Lazy Switch, which answers the same question by not running the consumer at all.

Categoryobvpm/gates

Inputs (2)

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

Outputs (2)

NameTypeDescription
imageIMAGEThe 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.