Nodes/BrainDead Nodes/BD For Each Run
ComfyUI Node

BD For Each Run

Iterate a typed list across your queue

By BizaNator·Created 8 months ago·Updated 3 days ago· 15
BD For Each Run
  • input_1
  • input_2
  • input_3
  • input_4
  • input_5
  • input_6
  • input_7
  • input_8
  • input_9
  • input_10
  • input_11
  • input_12
  • input_13
  • input_14
  • input_15
  • input_16
  • data
  • label
  • current_index
  • total_count
  • is_last
  • status
labelsalbedo normal roughness metallic ao
modesequential
manual_index0
resetfalse
workflow_iddefault
label_prefix_

The classic ComfyUI problem this solves: you have five images that each need the same downstream treatment - upscale, save, whatever - and you don't want to wire five parallel chains. BD_ForEachRun gives you up to 16 typed input slots (input_1 through input_16), and each time you queue a Run, it emits the next wired input plus its label. One chain downstream, run N times.

It's the "iterate over data" sibling to the pack's BD Bulk Save (which saves N files in one Run) - the README's rule of thumb is clean: Bulk Save when the downstream is just saving; ForEachRun when the downstream is more complex, like a per-iteration upscale before save, or a Qwen edit that needs to actually re-execute per item. Empty input slots are skipped, and the labels list aligns with the wired (non-empty) inputs.

How it works

State lives per workflow_id inside the node. In sequential mode (default), each queued Run advances to the next wired input, wrapping around with an iteration counter. manual mode picks a specific slot by manual_index. single always emits input_1. The reset toggle is edge-triggered: when it flips from false to true, the next Run starts back at the first wired input.

The node doesn't hold a batch or loop internally - it's stateful across Runs, which is why it suits "queue the workflow N times" workflows.

What comes out

  • data - the current input (any type: IMAGE, MASK, STRING, whatever you wired).
  • label - the label for this item, with label_prefix prepended. Default prefix is _, so label albedo comes out as _albedo - designed to drop straight into a save node's suffix.
  • current_index / total_count / is_last - bookkeeping outputs for downstream logic (e.g. "skip this on the last item").
  • status - a text line reporting which slot fired and the current iteration.

The typical setup

BD_DerivePBR maps (albedo, normal, roughness, metallic, ao)
  → input_1..input_5 of BD_ForEachRun
labels: "albedo\nnormal\nroughness\nmetallic\nao"
  → queue 5 runs → each emits one map + its label
  → downstream BD SaveFile uses label as the suffix

Queue five times and you've saved all five maps through a single save chain. That's the whole point: the per-item labels mean your save filenames stay correct without you hand-naming anything.

Install

Part of the BrainDead pack:

cd ComfyUI/custom_nodes
git clone https://github.com/BizaNator/ComfyUI-BrainDead
cd ComfyUI-BrainDead
pip install -r requirements.txt

Or search "BrainDead" in ComfyUI Manager and restart. Pure orchestration logic - no extra dependencies, just a current ComfyUI (the pack uses the V3 extension API).

Troubleshooting

  • It errors "no inputs wired" - every slot is empty; the node needs at least one. Remember, empty slots are skipped, so a partially wired list just works with fewer items.
  • Labels don't line up - labels align with wired inputs after skipping empties, not with slot numbers. If you left a hole in the middle, the label you thought was for input_3 now matches input_4.
  • Two ForEach nodes fight each other - give each a distinct workflow_id.
  • It never restarts from the top - that's sequential mode by design; flip reset or use manual_index.
Category🧠BrainDead/Prompt

Inputs (22)

NameTypeDefaultDescription
labelsSTRINGalbedo normal roughness metallic aoOne label per line, aligned with the WIRED inputs (after skipping empty slots). If labels list is shorter than wired inputs, missing labels emit as empty string.
modeoptCOMBOsequentialsequential: cycle one per Run. manual: pick by manual_index. single: always emit input_1.
manual_indexoptINT00–15
resetoptBOOLEANfalseEdge-triggered: when transitions False→True, the next Run starts at the first wired input.
workflow_idoptSTRINGdefaultUse distinct ids if you have multiple ForEach iterators.
label_prefixoptSTRING_Prepended to each label in the output. Default '_' so labels become save suffixes (e.g. label='albedo' → output '_albedo'). Set empty for raw labels.
input_1opt*Input slot #1. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_2opt*Input slot #2. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_3opt*Input slot #3. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_4opt*Input slot #4. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_5opt*Input slot #5. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_6opt*Input slot #6. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_7opt*Input slot #7. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_8opt*Input slot #8. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_9opt*Input slot #9. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_10opt*Input slot #10. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_11opt*Input slot #11. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_12opt*Input slot #12. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_13opt*Input slot #13. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_14opt*Input slot #14. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_15opt*Input slot #15. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.
input_16opt*Input slot #16. Wire any data type (IMAGE, MASK, etc.). Empty slots are skipped.

Outputs (6)

NameTypeDescription
data*
labelSTRING
current_indexINT
total_countINT
is_lastBOOLEAN
statusSTRING