π Array For Each
ComfyUI has no loop, so here's the next best thing
- Item
- Count
- Is Last
The honest framing
The name says "for each", which sounds like iteration. It isn't. ComfyUI has no loop construct - the graph is evaluated once, backwards from its output nodes - so no custom node can honestly promise you "run this subgraph N times" from inside the canvas. What Array For Each actually does is index bookkeeping: you give it a list and an index, it hands you that item, the total count, and whether you've hit the last one.
Given that, it's a better node than the name suggests. Set up right, it's how you walk a list across a batch of queued runs without retyping anything.
How it works
Split on newlines, trim if asked, bounds-check, return items[index]. Simple. Two behaviours are worth knowing precisely.
First, the bounds check is a hard failure: asking for index 6 of a 4-item list raises Index Out of Range, which stops the run. Second, Is Last is computed as index == count - 1 - a plain equality against the count it just computed. It does not detect "we've gone past the end"; it detects "this is the final item". Feed it an index beyond the end and you get an exception, not a True.
The pattern that actually works
Here's the trick, and it leans on one of the oldest pieces of ComfyUI machinery: the control_after_generate widget that sits under every integer. Set your index to come from an integer primitive with that control set to increment, and every time you hit Queue Prompt the index advances by one. The queue runs, the node reads item 3, then item 4, then item 5. You have a manual iteration loop that costs one integer widget.
Wire Is Last into whatever decision needs it - stop queueing, switch to a different prompt branch, log that the batch is done - and Count into a text preview if you want to see how far along you are. Be aware of the classic seed trap in a new costume: depending on your "widget control mode" setting, that increment can fire after the run rather than before it, so the number on screen is what comes next. If your indices feel off by one, that's why, and the fix is the global widget-control-mode setting, not this node.
The alternative pattern is the boring one: don't iterate at all. If you have 20 prompts and want 20 images, a text list with π Array Get Item plus batch size is usually less fragile than driving an index by hand. Array For Each earns its place when the item is a path or a stateful thing - a filename to load, a folder to clean - where batching doesn't apply.
Inputs and outputs
Array is socket-only (force_input), so no pasting - feed it from π List Files, π Array From Text, π Array Filter, π Array Slice.
Index is the iteration counter: zero-based, and out-of-range values raise rather than returning empty. Trim Items (on) cleans the returned line.
Outputs: Item (STRING - the current element), Count (INT - total items, constant across the walk), and Is Last (BOOLEAN - true on the final element). Item is the one that goes into your prompt, path, or loader; Is Last is the one that makes the walk terminate cleanly.
Install
Manager: Extensions β Node Pack β search "Honda Nodes" β Install β restart. Manual:
cd ComfyUI/custom_nodes
git clone --depth 1 https://github.com/Avaray/honda-nodes.git
cd honda-nodes
python install.py # ComfyUI's python; portable Windows: ..\..\..\python_embeded\python.exe install.py
Nothing in this node needs the downloaded jq/ime binaries, but run the installer anyway if you plan to use the JSON or metadata nodes in the same pack. Requirement: ComfyUI 0.38.0 or newer - honda-nodes is pure V3 schema, so an older frontend shows you nothing at all.
Common issues
Index out of range mid-batch. Your list got shorter than your counter - usually because a π Array Filter upstream changed, or because you trimmed items and the count dropped. Re-check Count against your starting index before queueing.
A skipped item. A blank line in the source list. For Each does not ignore empties, so a trailing newline is a real (empty) item and index N will return nothing. Run the list through π Array Filter with Remove Empty on first; that's what it's for.
Nothing runs. Non-output node, so it must feed something that executes - a prompt encoder, a path input, a preview, a save.
If you're coming from a scripting background and this feels like a lot of ceremony for a for loop: yes. It is. That's the shape of the platform, not the shape of the node - the pack is giving you the smallest honest building block and leaving the looping to the queue button.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| array | STRING | Newline-separated array string. | |
| index | INT | 0 | Zero-based index of the current iteration. |
| trim_items | BOOLEAN | true | Strip leading and trailing whitespace from each item. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| Item | STRING | β |
| Count | INT | β |
| Is Last | BOOLEAN | β |