Loop End (XJ)
The bottom half of the loop — where the magic (and the quirks) live
- flow
- value1
- value2
- value3
- value4
- value5
- value6
- value7
- value8
- value9
- value10
- value11
- value12
- value13
- value14
- value15
- value16
- value17
- value18
- value19
- value20
- value1
- value2
- value3
- value4
- value5
- value6
- value7
- value8
- value9
- value10
- value11
- value12
- value13
- value14
- value15
- value16
- value17
- value18
- value19
- value20
Loop End is the exit ramp for the XJNodes loop system. Loop Start opens a loop, this node closes it - and unlike its partner, it does the genuinely hard work. Each pass it checks whether the iteration count is done, and if not, it reconstructs the entire loop body graph for the next pass. When the loop finishes, it hands you the final values: up to 20 of them, value1 through value20, carrying whatever state your loop accumulated.
Here's what that buys you in practice. You run a batch of generations inside a loop, and instead of getting 20 separate images back that you have to assemble, you accumulate them into an image list across iterations and let Loop End hand you the finished list. The README calls the pack's list-preservation behavior its featured trick: lists stay lists through the loop, no silent auto-expansion. That's what makes accumulation patterns - "gather one image per pass into a list" - actually workable.
How it works
The mechanism is ComfyUI's subgraph expansion, and it's fiddly enough that the pack's own docs (loop-system.md) spend pages explaining it. The short version: Loop End traces back through every node that feeds it, collects the ones inside the loop, clones the whole body into a fresh subgraph for the next iteration, and re-wires it. It also special-cases output nodes like PreviewImage and SaveImage so they re-execute every pass instead of only the last one.
Then there's the double-wrapping workaround. ComfyUI's link resolution has a quirk that can silently strip a dimension off batched outputs (read: lose the batch dimension on your accumulated images). XJNodes compensates by returning values doubly-wrapped, and the code comments walk through exactly why. You don't need to understand it to use it - you need to know it exists, because it's why the pack tells you lists stay intact, and it's the difference between a loop that works and one that mangles your tensors.
Inputs and outputs
- flow - the FLOW_CONTROL wire from Loop Start. This is mandatory and it's how Loop End knows which loop it closes
- value1 … value20 - any-type inputs, receiving the loop body's results each pass
Outputs are the final value1 … value20 after all iterations. These are what you wire to wherever the loop's result should go.
Installing it
Same pack install. ComfyUI Manager → search "ComfyUI-XJNodes" → install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/alexjx/ComfyUI-XJNodes
# restart ComfyUI
No extra dependencies. Category: XJNodes/Flow. This node uses the comfy_execution graph machinery, so if you're on a very old ComfyUI, update it first - loops need modern internals.
Where it gets weird
Three things to know before you rely on it. First, total is owned by Loop Start, and total=0 there skips the body - Loop End just returns the initial values. Second, the double-wrapping workaround means output list handling is subtle; if a loop-fed list comes out with the wrong shape, it's the known quirk, not your wiring, and the docs are the place to verify your pattern. Third, loops and previews: a PreviewImage inside a loop body re-executes every pass, which is great for watching progress and a guaranteed flood of images at the end. Use Save Image with the iteration index in the filename, or accept the preview storm. Loops in ComfyUI are still advanced territory - the community has wanted them for years and the working implementations are few - but this pair is one of the honest ones.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| flow | FLOW_CONTROL | — | |
| value1opt | * | — | |
| value2opt | * | — | |
| value3opt | * | — | |
| value4opt | * | — | |
| value5opt | * | — | |
| value6opt | * | — | |
| value7opt | * | — | |
| value8opt | * | — | |
| value9opt | * | — | |
| value10opt | * | — | |
| value11opt | * | — | |
| value12opt | * | — | |
| value13opt | * | — | |
| value14opt | * | — | |
| value15opt | * | — | |
| value16opt | * | — | |
| value17opt | * | — | |
| value18opt | * | — | |
| value19opt | * | — | |
| value20opt | * | — |
Outputs (20)
| Name | Type | Description |
|---|---|---|
| value1 | * | — |
| value2 | * | — |
| value3 | * | — |
| value4 | * | — |
| value5 | * | — |
| value6 | * | — |
| value7 | * | — |
| value8 | * | — |
| value9 | * | — |
| value10 | * | — |
| value11 | * | — |
| value12 | * | — |
| value13 | * | — |
| value14 | * | — |
| value15 | * | — |
| value16 | * | — |
| value17 | * | — |
| value18 | * | — |
| value19 | * | — |
| value20 | * | — |