Foreach List End Ovum
The close bracket of ComfyUI's most misunderstood loop
- flow_control
- remaining_list
- accum
- result
ComfyUI doesn't have loops. It has a trick that feels like loops, and Foreach List End Ovum is the closing half of it. Its opening partner, ForeachListBeginOvum, pops one item off a list on each pass; this node is where the iteration ends and the accumulated result comes out. If you've ever stared at a workflow with a "Foreach" pair and wondered what on earth is wired to what - you're not alone, and the pack author knows it.
The README is disarmingly honest about the lineage: "I think I just stole these from easyUse to learn how they worked!" That's not a red flag, it's the actual history. The easyUse foreach pattern is one of the standard ways people build loops in ComfyUI, and the author even wrote a community guide to easyUse loops (r/comfyui, "Guide to easyUse for Loops") after watching everyone say "I can't work it out." This node is Ovum's take on that same pattern.
How it works
The loop is a graph-expansion trick, not a runtime for loop. On each execution, ForeachListEndOvum checks the remaining_list. If items are left, it clones every node sitting between the Begin and End nodes, feeds the remaining list back through the Begin node with your accumulator carried along, and re-runs that mini-graph for the next item. When the list finally empties, it returns the accumulator as result. Each pass ticks a progress readout ("X/Y steps") in the node's title bar.
That means the loop body is anything wired between Begin and End - a sampler, a text build, a crop - not just math. You can loop an entire sub-pipeline per item.
Wiring it - get this exactly right
The tooltip on the inputs is the whole game: "Directly connect the outputs of ForeachListBeginOvum to 'flow_control' and 'remaining_list'."
- flow_control - connect Begin's
flow_controloutput here. It's the control signal that tells the node which loop you belong to. - remaining_list - connect Begin's
remaining_listoutput. This is how the loop tracks what's left. - accum - the accumulator. Wire the value your loop body produces back in here (Begin's
accum/valueoutput feeds the loop body, and the loop body's output comes back into this port). - Output:
result- the final accumulated value once the list is exhausted.
Use CreateEmptyList (also from Ovum) as the seed, or set Begin's init_accum to start from a non-empty accumulator. If the loop body should collect per-item results into a list, MapStartOvum/MapEndOvum do that merge for you automatically - those are the friendlier variant if you just want "run this per item and collect a list."
Installing it
Part of sfinktah/comfy-ovum:
cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum
or search comfy-ovum in ComfyUI Manager, then restart. No models to download.
Where people get burned
Three classic mistakes. First, wiring the loop backwards - Begin's outputs must go to End's flow_control and remaining_list, and the node will warn you (or fail weirdly) if you guess. Second, forgetting the accumulator port entirely, so the loop body's output is discarded and result comes out empty. Third, expecting cheap iteration: because each pass clones the subgraph, a 10,000-item list means 10,000 expanded nodes in memory. Keep loops small, and remember that any node in the loop body that needs to "reset" each pass can fight you - that's what the pack's Uncachable List Copy helper exists for. Get the wiring right once, though, and it's genuinely the most expressive loop pattern in ComfyUI.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| flow_control | FOREACH_LIST_CONTROL | Directly connect the output of ForeachListBeginOvum, the starting node of the iteration. | |
| remaining_list | ITEM_LIST | Directly connect the output of ForeachListBeginOvum, the starting node of the iteration. | |
| accum | * | Connect the accumulated outputs processed within the iteration here. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| result | * | This is the final output value. |