Pipe Set Any
Name a value, drop it in the pipe, one wire from now on
- value
- pipe
- pipe
Every big ComfyUI graph gets to the same point: the model, the clip, the vae, the positive and negative conditioning, the latent, the steps, the cfg, the seed. Twelve values that nearly every node downstream wants, dragged as twelve separate wires across the whole canvas. Pipe Set Any is how this pack's version of the fix works - you give a value a name and put it into a UTILITY_ANY_PIPE, and from then on one wire carries the bundle.
If that idea is new to you, the useful framing is that this isn't a feature, it's a pattern several packs invented independently (rgthree's Context, Efficiency Nodes, Easy-Use's pipe, Apt_Preset's RUN_CONTEXT). comfyui-node-plumbing.md covers the whole family and its trade: the single wire is legible, and it hides which version of each value is inside it.
Inputs and output
key- a STRING, default"value". The name. Case-sensitive, and you will type it again in a getter, so name it something you won't misspell.value- any-type. The thing being stored.pipe- optional. Leave it unwired and the node starts a fresh, empty pipe for you. Wire it and the new field is added to what's already there. That optionality is what lets you chain: one setter per value, each feeding the next, ending in one wire.
One output: pipe.
The two mechanisms worth knowing
The pipe is immutable, and that's a feature. Each Set returns a new pipe with that field replaced (or appended, if the key is new) rather than mutating the one it was given. In concrete terms: if you branch one pipe down two paths and each path sets its own field, neither branch can stomp the other's data - the two paths each hold their own version and both are correct along their own route. A dict-style pipe shared by reference doesn't give you that, and the resulting bugs are miserable to find because both branches look right in isolation. Setting the same key twice on the same path, on the other hand, is last-write-wins - the later setter overrides.
The value has to arrive as exactly one scalar. Under the hood these nodes are declared as list-input nodes, so ComfyUI delivers each input as a transport list, and this one requires that list to contain exactly one item. Wire in something list-producing and you get "requires exactly one scalar execution value; received N items" rather than a subtle wrong answer. It's a confusing message the first time, and it's guarding the right thing: a pipe field is one value, and if you want many, the list namespace is next door in Pipe Set List.
Where it fits
The shape this node is built for is a headers region: at the top of the canvas, one setter per value, chained into a single pipe wire that runs down the left side. Every working node then taps it with Pipe Get Any for what it needs and Pipe To/Edit Any to write back what it changed. Whether that's an improvement over explicit wires depends on size - pipes pay off on a graph you can't read anymore, and cost you on a graph you can, because a pipe connection is always present and the contents can still be wrong.
Two habits that make pipes survivable. Name keys after their contents and their type (steps_int, masks_list), since the container is untyped and won't help you. And build the pipe after the loader or LoRA that changes what goes in it - writing the base model into a pipe and then adding the LoRA afterwards is the standard stale-context bug, and nothing will warn you.
Install
Manager: search ComfyUI Utility Suite (publisher tom-m) → install → restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/tom-m-2020/ComfyUI-Utility-Suite
No models to download; the pack's single requirement is opencv-python-headless, and this node is pure Python. It's authored against ComfyUI's V3 node API, which is what defines the UTILITY_ANY_PIPE socket type - so on a ComfyUI older than that API you'll install the pack and see no nodes at all.
Troubleshooting
"requires exactly one scalar execution value." Something upstream is a list. Put a selector in between (Mask From List picks a single mask out of a mask list; the pipe's list namespace is the alternative if you wanted to carry them all).
"has no field 'x'" from the getter. The key never got set - check the spelling on both ends, and check that the setter isn't on a bypassed node or in an execution path that didn't run.
The build got slow and the graph is unreadable. That's not this node's fault specifically, but pipes make wire-count problems invisible. If you're actively iterating on one region of a graph, wire those values explicitly and keep the pipe for the parts that are stable.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| key | STRING | value | — |
| value | * | — | |
| pipeopt | UTILITY_ANY_PIPE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| pipe | UTILITY_ANY_PIPE | — |