Join Image Lists
Glue two batches together and keep the count
- In1
- In2
- Joined
- Sizes
You generated four candidates, upscaled two of them, and now you want all six in one folder for a look. Join Image Lists is the node that stacks them into one list without any of the images touching each other.
What it is
Two required inputs, In1 and In2, and more slots that appear on their own: connect In3 and In4 shows up, and so on with no limit. Outputs are Joined - everything, in slot order - and Sizes, an INT list giving the length of each connected input.
Both outputs are lists. That word is doing real work here, and it's the part that catches people.
How it works
The node declares INPUT_IS_LIST, so it receives the raw lists from its inputs rather than the usual single value, and it concatenates them in slot order. Sizes is the audit trail: [4, 2] means the first input contributed four images and the second two.
The OUTPUT_IS_LIST flag is what makes it interesting downstream. It doesn't hand the next node one batch of six - it makes the next node execute once per element. That's why joining lists is the standard move for per-image processing: one saved file per image, one prompt per image, one upscale pass per image, no loop node required.
Two structural details worth knowing: slots are renumbered to match what you see, so disconnecting a slot in the middle removes it and renumbers the rest rather than leaving a gap - meaning slot order is always visual order, top to bottom. And the backend accepts any InN name, so an API prompt can list In3, In4 directly without the frontend managing anything.
When to reach for it
- Two variants, one output folder. Upscaled with 4x-UltraSharp on one branch and a lighter ESRGAN on the other; join and save both. Note that for a pure "more pixels" job a plain interpolator is the cheap, correct answer - it adds no detail and can't hallucinate, and it's fast enough that running both is free.
- Merging seed sweeps. Two generation branches, one save node, filenames numbered by the save node's counter.
- Feeding a per-image pipeline. Joining lists ahead of a node with
OUTPUT_IS_LIST-aware inputs makes it run once per image, which is how you get per-image prompts or per-image settings without duplicating the graph.
The Sizes output is the sanity check for when that count goes wrong. Wire it into something that displays numbers - or into Math Expression, which can add them up - and you can see at a glance that your join produced 6 items rather than 4.
Installing it
ComfyUI Manager → search ComfyUI-BCNodes → install → restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/0xBeycan/ComfyUI-BCNodes
pip install -r ComfyUI-BCNodes/requirements.txt
Reload the browser tab after the restart: the growing slots are managed by frontend JavaScript (web/js/join_image_lists.js), and a stale tab is the usual reason a new slot doesn't appear. It's registered under BCNodes/image.
Where people get burned
A list is not a batch. An IMAGE batch is one tensor with N frames; a list is N separate items. Most nodes are happy either way, but they don't mean the same thing - a node that averages across a batch will treat six joined images as six runs of one image. If the numbers look odd downstream, this is why.
Sizes must match for anything that stacks. This node joins; it does not resize. Joining a 1024×1024 batch to a 1536×1536 batch gives you a list of two different shapes, and the first node that tries to stack them will fail. Resize before you join, not after.
Nothing in this node saves anything. Bulk-saving joined lists is a Save Image node's job, and the filename counter is what keeps them from overwriting each other.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| In1 | IMAGE | — | |
| In2 | IMAGE | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| Joined | IMAGE | — |
| Sizes | INT | — |