.internal/while_loop_end
The node that makes ComfyUI loop — recursion in a graph that can't
- flow
- initial_value0
- 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
- value0
- value1
- value2
- value3
- value4
- value5
- value6
- value7
- value8
- value9
- value10
- value11
- value12
- value13
- value14
- value15
- value16
- value17
- value18
- value19
This is the closest thing in the pack to actual magic: a node that makes an acyclic graph loop. ComfyUI workflows are directed acyclic graphs - no feedback, by design - so the only way to get a loop is to rebuild part of the graph at runtime and run it again with new inputs. That's dynamic graph expansion, and __y_i_u__while_loop_end is the node that orchestrates it. It's the close bracket of the while-loop: it looks at the condition, and either exits the loop or clones the subgraph between itself and the loop start, re-runs it with the updated values, and returns the result.
It's an .internal node, hidden from the node menu by the pack's front-end code. You'll meet it in saved workflows, most notably inside the yiuUpscaleLoopStart/END machinery, where it's the engine that advances the step counter and feeds the next iteration's image back in. The upscale loop's END builds one of these internally on every step; you generally never touch it directly.
How it works
When the condition is false, the loop is done: it returns the initial_values you wired in, straight through. When the condition is true, it does the recursive part: it walks the graph to find the loop body (everything between the matching start node and itself), clones that subgraph with GraphBuilder, writes the current iteration's values back into the start node's inputs, and returns the recomputed outputs - which is how each pass "feeds forward" even though the graph you saved is flat.
There's a recurse_target string input (default empty) that lets it resolve which node to recurse into when node IDs get ambiguous after expansion - mostly useful for debugging the machinery, not for day-to-day use.
Inputs
- flow - the FLOW_CONTROL from the loop start.
- condition - BOOLEAN; false exits the loop, true iterates.
- recurse_target - optional internal string.
- initial_value0 … initial_value19 - the loop-carried state.
Outputs
value0 … value19 - the iteration's results (or the initial values, when the loop exits).
Installing it
Part of yiu_comfy_nodes by leizingyiu:
cd ComfyUI/custom_nodes
git clone https://github.com/leizingyiu/yiu_comfy_nodes
restart ComfyUI. No extra dependencies.
Where people get burned
- Don't build this by hand. It's hidden from the menu for a reason, and the wiring it expects (a matching start node, a resolvable loop body) is easy to get wrong. If you need a loop, use the upscale START/END pair or another pack's loop nodes.
- It needs a recent ComfyUI. The
GraphBuildergraph-expansion API is required; on older installs the machinery errors with "GraphBuilder is not available." This is a version problem, not a config problem. - Every iteration is a re-execution. The loop re-runs the whole contained subgraph, so anything inside the body (samplers, loaders) executes per pass. Keep the body small and deterministic - random nodes inside a loop are a recipe for drift.
- The condition gate is your kill switch. No built-in iteration cap. If whatever computes
conditionnever goes false, the loop runs until you stop it. The upscale loop wires its step counter here precisely so that can't happen.
Inputs (23)
| Name | Type | Default | Description |
|---|---|---|---|
| flow | FLOW_CONTROL | — | |
| condition | BOOLEAN | — | |
| recurse_targetopt | STRING | — | |
| initial_value0opt | * | — | |
| 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 (20)
| Name | Type | Description |
|---|---|---|
| value0 | * | — |
| value1 | * | — |
| value2 | * | — |
| value3 | * | — |
| value4 | * | — |
| value5 | * | — |
| value6 | * | — |
| value7 | * | — |
| value8 | * | — |
| value9 | * | — |
| value10 | * | — |
| value11 | * | — |
| value12 | * | — |
| value13 | * | — |
| value14 | * | — |
| value15 | * | — |
| value16 | * | — |
| value17 | * | — |
| value18 | * | — |
| value19 | * | — |