End ForEach (misc)
The closing bracket of a graph-drawn loop
- value
- combined
ForEach (misc) opens a loop; End ForEach (misc) closes it. Where ForEach unpacks a combined bundle and pushes each value through the loop body one at a time, End ForEach is the sink at the far end: it collects the per-iteration results coming off your loop's last node and repacks them into a fresh combined (PRIMITIVES) bundle. Run the loop with four prompts and you'll get back a bundle of four results - feed that into Split Primitives (misc) and they're individual typed outputs again, ready for whatever comes after.
If you've written a for-loop in any language, the mental model is already in your head: ForEach is for value in bundle:, the nodes between are the loop body, and End ForEach is where the accumulated output gets gathered on the other side.
How it works. This is the mirror of ForEach's list-execution trick. End ForEach declares INPUT_IS_LIST, which tells ComfyUI "give me the whole list at once" rather than running once per item. So while every node in the loop body fires N times (once per element), End ForEach fires once and receives all N results as a list in a single call. It flattens that list, re-infers each value's type, and packs it back into the same {"values", "types"} structure Combine Primitives uses. Even blocked executions (items that hit an ExecutionBlocker somewhere in the body) get skipped during flattening rather than ending up as garbage in the output bundle.
The input and output. One input: value, typed * and deliberately kept type-blind even after you connect it - so the loop body's output can be anything, images included. One output: combined (PRIMITIVES). There are no widgets; the node is entirely wiring. Output names on a following Split Primitives (such as STRING_01, STRING_02) sync back to the types the original Combine recorded, which is a nice end-to-end touch: the bundle remembers what each slot was, even after a round trip through a loop.
Install. Same as the rest of the pack, from ComfyUI/custom_nodes:
git clone https://github.com/wraith-executioner-year-2/comfyui-misc/
Restart ComfyUI; it's in the misc category. No models, no requirements - just the Python node and the web extension that keeps its wildcard socket behaving.
Where people get burned: the natural traps are loop traps, not this node's. First, an empty loop (empty combined in, or every iteration blocked) leaves you with an empty bundle - that's correct, but a downstream node that assumes at least one result will break, so check length from the Split before doing anything fatal. Second, because the loop body runs N times, an expensive node inside it multiplies your runtime N-fold; keep loads outside the loop. And keep an eye on what the body's last node emits - End ForEach packs whatever arrives on value, so if the loop's final node isn't the one you actually care about, the bundle will be full of the wrong things and the graph won't tell you.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| value | * | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| combined | PRIMITIVES | — |