Bundle to List (obvpm)
The node that makes everything downstream run once per value
- in
- list
Two things in ComfyUI get lumped together and really shouldn't be: a batch and a list. A batch is one tensor holding N images, which is why every image in it must be the same size. A list is a promise to the executor - "call the next node once per item" - and nothing about the items has to match.
Bundle to List converts the second thing out of the first thing. It takes an obvpm bundle (a plain name/value mapping travelling on one wire) and turns the values into a ComfyUI list, in field order.
Why you'd care: Load Images & Compose, the same pack's reference-sheet node, hands you its individual layers as a bundle on extras. You can't batch those - a 300×200 crop next to a 3000×2000 crop can't share a tensor - but you can list them, so an upscaler or a Save Image downstream runs once per layer, each at its own native size. That's the case it was built for.
How it actually works
In ComfyUI a list is not a type you can smuggle around inside a value. It's a flag on an output socket - OUTPUT_IS_LIST. That's the whole reason this node exists as a separate node: Unbundle's outputs are generic (*) and identical for every bundle, so none of them can be declared a list. Bundle to List has exactly one output, it declares the flag, and the list marker shows on the socket and nowhere else.
The implementation is about as thin as a node gets: it reads the bundle and returns list(bundle.values()). Which gives you four behaviours worth knowing before you wire it up:
- Order is field order. Item 3 is the third field, whatever it's called.
- Empty fields keep their slot. A field that's wired but empty stays
Nonein position, so items don't shift up on you. - A nested bundle is one item, a dict, not flattened into its innards.
- An empty bundle stops the run by name -
Bundle to List: the bundle is empty, so there is nothing to list. (From Load Images & Compose: every layer is muted.)Without that check you'd get a missing-argument error from the next node that names nothing useful.
The inputs that matter
There's one input and no settings panel at all:
in- the bundle to turn into a list. Wire it from an Unbundle (the usual pattern is Load Images & Compose → Unbundleextras→images_bundle→ here), or from anything else that emitsOBVPM_BUNDLE.
Output: list - the bundle's values, one list item per field, in field order. That socket is what carries the list marker, and it's the only socket in the pack that can.
Before you flip a bundle into N runs, drop Peek Bundle (same pack, free) upstream of it: one line per field, shape for images, the value itself for numbers. Cheap insurance against finding out on item 4 of a six-minute run that a field was None.
Installing it
Manager is the easy path: open ComfyUI Manager and search for obvpm or comfyui-obvpm. Manually, it's the standard ritual:
cd ComfyUI/custom_nodes
git clone https://github.com/chanon/comfyui-obvpm
# restart ComfyUI
No pip step: pyproject.toml deliberately declares an empty dependency list - every third-party import it makes is already in ComfyUI's own requirements, and re-pinning torch or numpy could contradict core's pins on your install. It does ship frontend JavaScript, so after installing or updating, hard-refresh the browser tab if a node looks stale or empty.
Every node in the pack has (obvpm) appended to its name, so typing obvpm into the node search menu finds all of them.
Where people get burned
Everything downstream runs once per item, not just the node you were thinking of. Wire this into a Save Image and you get one file per value; wire it into a sampler chain and you get a whole generation per value. The node description is unusually blunt about it: keep the list away from a generation unless you mean one run per value.
"The node doesn't exist." Bundle to List is new in 0.2.15 (2026-10-12), so an install older than that simply doesn't have it. Update the pack; the same release also raised Bundle and Unbundle to 128 fields, and older versions quietly drop pins past 16.
Wiring a non-bundle into in is refused, which is the right call - you get Bundle to List: expected a bundle rather than a mystery downstream.
One bundle per node. And note what the output type is: *. A bundle can hold anything - images, latents, models, text, a nested bundle - so this will happily hand a downstream node a list of mixed types. Neither end will complain. Whether that list means anything is entirely on the consumer you wired it to.
One thing about the pack itself: it's a one-person project (chanon, who also ships comfyui-obvpm-timeline), and it has essentially no Reddit footprint - an exact-phrase search for "obvpm" across the community corpus returns nothing. So the README and the CHANGELOG are your documentation, and the CHANGELOG is genuinely good. Read it after every update; this pack moves in small, frequent releases.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| in | OBVPM_BUNDLE | The bundle to turn into a list. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| list | * | The bundle's values, one list item per field, in field order. |