Multiline Text Iterator
Queue a list of prompts and let each run grab the next one, automatically
- text_line
- count
Multiline Text Iterator (class BatchIteratorMultiLine) is the one node in this pack I'd actually reach for unprompted. Paste a multiline list of prompts into it, queue N runs, and each run outputs the next line - then, when you run out of lines, it blocks downstream so the loop stops cleanly instead of erroring or repeating. It's the whole "prompt queue" workflow compressed into a single node, and it's the most straightforwardly useful thing teddy1565 shipped here.
The author's description says it in one line: "Each Run Task (Prompt), Will Iterator Once, Output Single String." Where this shines is batch variation work - N compositions, N seeds, N negative prompts - where you don't want to hand-assemble a batch or wrestle with a scheduler node. Queue your runs, let each one pull the next item, and let the iterator end the party when the list is exhausted.
How it works
The current position is persisted per persistence_memory_key_id in a global dict. Each execution reads the index, splits text on delimiter (stripping empties when skip_empty is on), returns that line, and advances the index. When the index runs past the last line it behaves per mode:
fixed(default) - returns anExecutionBlocker, so downstream just doesn't run this pass. That's ComfyUI's "skip this branch quietly" signal, not a crash - which is exactly what you want for "I'm out of prompts, stop."overflow- wraps around (index mod line_count) and keeps yielding from the top, looping forever.
force_reset clears the stored index so the next run starts over at line one.
The inputs that matter
persistence_memory_key_id(STRING) - the name of your iterator's memory slot. Empty is asking for trouble; use a distinct id per iterator so they don't share position.text(STRING, multiline) - the prompt list.delimiter(STRING, default\n) andskip_empty(BOOLEAN, defaulttrue).mode(fixed/overflow) andforce_reset(BOOLEAN).
Outputs: text_line (STRING) - the current line, and count (INT) - and here's a trap: despite the name, count is the total number of lines in your text, not the current position. The source returns len(prompts). Don't build position-dependent logic on it.
Installing it
No dependencies, no model files - cleanest pack to install you'll see. ComfyUI Manager → search "AsyncOutput" → install and restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/teddy1565/ComfyUI-AsyncOutput
It's under AsyncOutput/BatchIterator/String - note the BatchIterator family sits outside the Deprecated(...) category, so this is the maintained side of the pack.
Where people get burned
The count output is the easy one to trip on - it's a line total, not an iterator position, and the naming doesn't tell you. Also, if you edit text mid-loop the iterator doesn't know; it just advances an index into whatever the text is now, so changing the list between runs can silently shift which prompt you get. And the position lives in process memory: restart ComfyUI and the iterator forgets where it was, which is usually fine (start over) unless you were resuming a long queue and expected otherwise.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| persistence_memory_key_id | STRING | — | |
| text | STRING | — | |
| delimiter | STRING | — | |
| skip_empty | BOOLEAN | true | — |
| modeopt | COMBO | fixed | - fixed: if iterate count >= len(promts): return (comfy_execution.graph.ExecutionBlocker(None), ) - overflow: if iterate count >= len(promts): current_index = current_index mod len(promts) |
| force_resetopt | BOOLEAN | false | If enabled, will force_reset data in global memory |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| text_line | STRING | — |
| count | INT | — |