Load Image Optional
The loader that can hand downstream nothing, on purpose
- IMAGE
- MASK
Take ComfyUI's Load Image, add a None entry to the top of its file dropdown, and make that entry output literal None instead of a picture. That's the whole feature - and it sounds like a downgrade until you've built a workflow with a reference image that's sometimes there and sometimes not.
Why anyone wants a loader that returns nothing
Half the interesting nodes in the ecosystem have a slot for a reference image: IPAdapter image conditioning, FaceID's face shots, InstantID working from a single reference, PuLID Flux, a relighting reference, a style frame. The moment you decide whether to use one, you're stuck with two bad options:
- Leave the optional input unwired. Now there's no way to turn it on without editing the graph, and you can't keep the branch you built.
- Wire in a dummy image. Now a placeholder is conditioning your generation, quietly, at whatever strength it was set to.
Load Image Optional gives you a third: the socket is populated by a node whose content is nothing. ComfyUI's engine convention is that an unwired optional input arrives at the node's code as None, and this loader reproduces that same signal from the data side - so any node already written to treat None as "no reference supplied" does the right thing with zero rewiring.
The catch, and you'll hit it first: the destination input has to be optional, and the node has to handle None. If it doesn't, you get a NoneType error at execution - loud, on the offending node, and a clear signal that this isn't an optional slot.
What it actually does
def load_image(self, image):
if image == "None":
return (None, None)
That's the delta. The rest of the file is core Load Image, near enough line for line: exif_transpose to fix phone rotation, 16-bit "I" images rescaled by 1/65535, convert to RGB, then /255 into a float32 tensor with a leading batch dimension. The second output is the mask:
- if the image has an alpha channel, the mask is the alpha channel, inverted (
1 - alpha) - so transparency becomes the masked area; - if it doesn't, the mask is a tensor of zeros the same height and width as the image.
Two outputs, named after their types: IMAGE and MASK. The image widget is a dropdown built from your ComfyUI input/ folder, with "None" always first, plus the usual in-node upload button (image_upload: True), so you can drag a file straight in.
It also inherits the loader's bookkeeping:
IS_CHANGEDreturns the file's hash - or the literal string"none"whenNoneis selected - which is why editing an image on disk and re-queuing reloads it instead of serving the cached tensor.VALIDATE_INPUTSchecks the file still exists, so a deleted or renamed file fails on this node with "Invalid image file: …" instead of exploding somewhere deep in the graph.
Install
This one comes from Mochorong (author mochorongo, MIT, v1.0.1 - five nodes, no footprint to speak of). It registers under the image category rather than Mochorong, so it appears near ComfyUI's own Load Image in the node menu - intentional, not a broken install.
ComfyUI Manager, search Mochorong. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/mochorongo/Mochorong
Restart ComfyUI after cloning. The registry one-liner from the README is comfy node install comfyui-mochorong.
No dependencies, no requirements.txt, no models - the pack imports torch, numpy, PIL and folder_paths, all already present, and asks for Python 3.10+. Nested clones (custom_nodes/Mochorong/Mochorong) are the usual reason a custom node never appears.
Trap list
NoneType/ "object has no attribute" downstream. You selected None and something in the chain needs a real image. Either wire a fallback branch or check that input is genuinely optional.Noneis not a black image. A black image is a real tensor and will be used as one;Nonemeans nothing was supplied. Nodes that test forNonewill skip; nodes that just do maths will crash.- The mask is zeros when there's no alpha. Fine for "nothing selected here"; wrong if you needed the image content as the mask.
- A file dropped into
ComfyUI/input/by hand doesn't show in the dropdown. The list is built when the node's inputs are defined, so refresh the node (or the browser tab) - or use the node's own upload widget. - File deleted after you picked it. That's the
VALIDATE_INPUTSmessage firing correctly. Re-upload or pick another.
Used well, it stops a shared workflow from being a rewire-every-time affair. Used carelessly, it's a None travelling into a branch that never expected one - at least that's a fast failure rather than a wrong picture.
Sources: Mochorong load_image_optional.py and README (read 2026-09-14); docs/knowledge/comfyui-node-plumbing.md for the null-output placeholder pattern and optional-inputs-arrive-as-None; docs/knowledge/identity-preservation.md for the reference-image node family (IPAdapter, FaceID, InstantID, PuLID) this pattern serves; docs/knowledge/comfyui-ecosystem.md for custom-node install expectations.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| image | COMBO | 2 options: None, example.png |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| MASK | MASK | — |