For Loop End
For Loop End is the node that's actually driving your loop
- flow
- initial_value1
- initial_value2
- initial_value3
- initial_value4
- initial_value5
- initial_value6
- initial_value7
- initial_value8
- initial_value9
- initial_value10
- initial_value11
- initial_value12
- initial_value13
- initial_value14
- initial_value15
- initial_value16
- initial_value17
- initial_value18
- initial_value19
- value1
- value2
- value3
- value4
- value5
- value6
- value7
- value8
- value9
- value10
- value11
- value12
- value13
- value14
- value15
- value16
- value17
- value18
- value19
What it is
For Loop End closes the loop opened by For Loop Start, and if you only understand one node out of the pair, make it this one - because this is the node doing the work. Start is mostly a friendly façade: it holds the total widget and hands out the iteration number. End is the part that rewrites your graph on every round.
You reach for it whenever you want a block of graph executed N times - batch a set of seeds, walk a list of prompts, run a refinement pass repeatedly, build a stack of frames - without physically duplicating the block.
How it works
ComfyUI doesn't have loops. It has dynamic prompt expansion: a node, while executing, can return a whole subgraph as its output, and the engine splices it in and keeps going. That's the mechanism in comfy_execution.graph_utils.GraphBuilder, and it's how every loop pack fakes iteration.
For Loop End uses it like this, once per round:
- It reads the node feeding its
flowsocket and pullstotaloff that For Loop Start. - It builds a
wcx_LoopStepnode wired to that Start'sindexsocket, withstep=1, producingnext_indexand acontinueboolean (next_index < total). - It builds a
wcx_WhileLoopEndwithcondition=continueandinitial_value0=next_index. - That While Loop End takes over the copying: it duplicates every node between Start and itself - the loop body - into a fresh pass, pushes this round's values into the copy's Start, and chains the next round's End under an internal
Recursename. - The copy runs, reaches its own End, and either stops (condition False) or expands again.
When continue finally comes back False, the innermost End returns the carried values and they bubble back out. So the valueN outputs here are the state as of the last round - post-loop, not per-round.
Sockets
Required: flow (WFLOW_CONTROL), which must come from a For Loop Start. Note this socket is declared rawLink internally, meaning it carries the link rather than a resolved value - that's how End knows which Start it belongs to, and it's why you shouldn't try to be clever with it.
Optional: initial_value1 … initial_value19 (wildcards). This is your feedback channel. Whatever you wire into these is what the next round's loop body receives, and whatever you leave unwired arrives as nothing on round two. The matching outputs, value1 … value19, are what's left after the loop finishes - one batch, one accumulated tensor, one final string, whichever way you built it.
There is no index here. The counter is managed by the injected Loop Step, and on the canvas it's surfaced by For Loop Start's index output.
Install
ComfyUI Manager, search ComfyUI-Practical-Tools, or:
cd ComfyUI/custom_nodes
git clone https://github.com/wenchengxiang/ComfyUI-Practical-Tools
Restart. This node is pure Python with no extra dependencies, models, or downloads - the pack's requirements.txt (onnxruntime, nvidia-vfx, openai) is for unrelated nodes, and the loader tolerates those failing one file at a time. Nothing about For Loop End cares.
Traps worth knowing
The step is hardwired to 1 here. For Loop End inserts its own Loop Step with step=1, so a for loop counts 0,1,2,3… If you want to walk every second or every 64th iteration, build the loop out of While Loop Start/End plus a Loop Step node you wire yourself - that's the only place the step widget is exposed.
The silent fallback. If the flow wire doesn't come from a For Loop Start - you bypassed the Start, or rewired something carelessly - End doesn't error. It passes the current values straight through and ends the loop. You get one iteration and no stack trace. When a loop "runs once and quits", check this first.
Only what's wired in gets copied. End finds the loop body by walking backwards from its own inputs, so any node in the visual block that doesn't feed into it isn't part of the loop. Groups and boxes are decorative to this node.
Output nodes inside the body fire every round. That's deliberate - the implementation goes out of its way to keep Preview Image / Save Image nodes attached in the copied region, including their subgraph variants. A nice feature (you watch each iteration land in the queue) and a mild footgun (a 40-round loop with a Save node writes 40 files).
Cost scales as total × body, plus memory. Everything inside the loop re-runs each round and ComfyUI holds onto the intermediates, so total is not a free dial. Loops that sample 50 times are 50 samples, and the accumulator you're building is genuinely resident in RAM by the end.
Inputs (20)
| Name | Type | Default | Description |
|---|---|---|---|
| flow | WFLOW_CONTROL | — | |
| initial_value1opt | * | — | |
| initial_value2opt | * | — | |
| initial_value3opt | * | — | |
| initial_value4opt | * | — | |
| initial_value5opt | * | — | |
| initial_value6opt | * | — | |
| initial_value7opt | * | — | |
| initial_value8opt | * | — | |
| initial_value9opt | * | — | |
| initial_value10opt | * | — | |
| initial_value11opt | * | — | |
| initial_value12opt | * | — | |
| initial_value13opt | * | — | |
| initial_value14opt | * | — | |
| initial_value15opt | * | — | |
| initial_value16opt | * | — | |
| initial_value17opt | * | — | |
| initial_value18opt | * | — | |
| initial_value19opt | * | — |
Outputs (19)
| Name | Type | Description |
|---|---|---|
| value1 | * | — |
| value2 | * | — |
| value3 | * | — |
| value4 | * | — |
| value5 | * | — |
| value6 | * | — |
| value7 | * | — |
| value8 | * | — |
| value9 | * | — |
| value10 | * | — |
| value11 | * | — |
| value12 | * | — |
| value13 | * | — |
| value14 | * | — |
| value15 | * | — |
| value16 | * | — |
| value17 | * | — |
| value18 | * | — |
| value19 | * | — |