Nodes/Comfyui-EzFlex-Presets/EzFlex-LoopStart
ComfyUI Node

EzFlex-LoopStart

The front door of a ComfyUI loop, and why round one is always empty

By blackbossokok·Created 2 months ago·Updated 19 days ago· 5
EzFlex-LoopStart
  • initial value1
  • initial value2
  • initial value3
  • initial value4
  • initial value5
  • initial value6
  • initial value7
  • initial value8
  • initial value9
  • initial value10
  • initial value11
  • initial value12
  • initial value13
  • initial value14
  • initial value15
  • initial value16
  • initial value17
  • initial value18
  • initial value19
  • initial value20
  • _ezfeed1
  • _ezfeed2
  • _ezfeed3
  • _ezfeed4
  • _ezfeed5
  • _ezfeed6
  • _ezfeed7
  • _ezfeed8
  • _ezfeed9
  • _ezfeed10
  • _ezfeed11
  • _ezfeed12
  • _ezfeed13
  • _ezfeed14
  • _ezfeed15
  • _ezfeed16
  • _ezfeed17
  • _ezfeed18
  • _ezfeed19
  • _ezfeed20
  • index
  • value1
  • value2
  • value3
  • value4
  • value5
  • value6
  • value7
  • value8
  • value9
  • value10
  • value11
  • value12
  • value13
  • value14
  • value15
  • value16
  • value17
  • value18
  • value19
  • value20
◄config{}►
◄index0►

You cannot draw a loop in ComfyUI. Not "it's awkward" - the engine rejects it. A link that points backwards is a dependency cycle, and the graph walker throws on it. Which is a problem, because the interesting jobs in 2026 are loops: generate a 30-second video in six chunks and feed each chunk the last frame of the one before it, or run the same face-detailer pass three times at descending denoise. So every pack that solves this does the same thing: it doesn't draw the loop, it unrolls it. The prompt gets rewritten between rounds - the body cloned, the next round's inputs written in as literal values - and the queue runs it as a straight line.

EzFlex-LoopStart is the node that surfaces what that unrolling produces: which round you're on, and the values carried in from the last one. It does exactly one job, and the pack's own comment says so - "hand the previous LoopEnd's product back to this round."

What the panel and the ports actually do

The panel has a single field: index, the starting round, 0 by default. Read-only at runtime. You set where the loop begins; the loop increments from there, one per pass.

Outputs, in order: index (INT) first, always - that's the one you wire into the index input of EzFlex-PromptHelper, EzFlex-MediaLoader, or EzFlex-TimeLine so each round reads the right card or the right segment. Then value1 through value20, which are dynamic: a port appears once you've connected something to the matching port on the LoopEnd, and not before.

Inputs: an optional index (leave it unwired and the panel value wins; wire it if an upstream node, like Easy-Use's forLoop index, should decide the start round) plus initial value1 through initial value20 - one per value port.

The initial values are the whole subtlety. Round one has no previous round, so valueN outputs whatever you put on initial valueN; from round two onward the fed-back value overrides it. If you leave an initial unwired, round one hands the downstream node nothing - which is fine for a node with an optional input, and a hard error for torch.cat, a VAE encode, or anything else that needs a real tensor. The classic case is the long-video chunk loop: LoopEnd.value1 receives the last frame of the current segment, LoopStart.value1 hands it to the next segment's conditioning - and on the first segment there is no last frame, so you feed the initial frame (or a still you want the motion to start from) into initial value1 and the body never sees a None.

Installing it

Same pack, same two lines. ComfyUI Manager → search EzFlex (pack title Comfyui-EzFlex-Presets) → install → restart. By hand:

cd ComfyUI/custom_nodes
git clone https://github.com/blackbossokok/Comfyui-EzFlex-Presets
# then restart ComfyUI

Dependencies are almost nothing: the only extra is mutagen, for reading audio/video tags - pip install -r requirements.txt inside the folder, or pip install mutagen. llama-cpp-python, gguf and onnx are optional and deliberately kept out of requirements so Manager never kicks off a compile. The pack wants ComfyUI 0.3.13+ because it uses the official i18n endpoint. It's a personal AI-assisted project with Chinese-first docs, so treat it as a power tool you debug yourself rather than a supported product - there's essentially no English-language discussion of it to fall back on.

Wiring it without hurting yourself

Full contract, in order: LoopStart.index → the index input of whatever needs to know which round it is. LoopStart.valueK → the body node that consumes the carried data. The body's output → LoopEnd.valueK. Done. Nothing goes from LoopEnd back to LoopStart on the canvas. The feed is implicit; a real wire closes the cycle and you get Dependency cycle detected.

When it doesn't work

  • Round one dies on a None. You skipped an initial value. Wire the same kind of data you expect LoopEnd to carry back.
  • It runs once and stops. No paired EzFlex-LoopEnd, or the End's round counter is 0. You'll see a line about it in the terminal - the loop nodes print rather than fail, so read the console, not the canvas.
  • Dependency cycle detected. You wired End → Start. Delete it.
  • The loop seems to skip the body. The body is defined by reachability: everything downstream of the Start, stopping at the End. Anything fed from outside the loop keeps its original wire and is not cloned, so it's computed once and reused.
  • Only the last round's values survive. That's EzFlex-LoopEnd working as designed - out1..out20 are the final round's carried values. To keep every round, carry a list: merge each round's product with EzFlex-MergeList and hand the merged list back through a valueK port.

One pleasant side effect: each round's clone gets different literal inputs, so the cache key changes and the body genuinely re-executes - no always-rerun tricks needed in the body.

CategoryEzFlex

Inputs (42)

NameTypeDefaultDescription
configSTRING{}Loop Start panel state (start round). Kept as a serialisable widget so the round counter survives save / load.
indexoptINT0Start round (0 = from the first). Also becomes the index output value of the first round. Leave unwired to use the panel value.
initial value1opt*Initial value 1. Used as value1 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value1 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value2opt*Initial value 2. Used as value2 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value2 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value3opt*Initial value 3. Used as value3 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value3 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value4opt*Initial value 4. Used as value4 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value4 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value5opt*Initial value 5. Used as value5 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value5 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value6opt*Initial value 6. Used as value6 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value6 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value7opt*Initial value 7. Used as value7 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value7 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value8opt*Initial value 8. Used as value8 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value8 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value9opt*Initial value 9. Used as value9 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value9 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value10opt*Initial value 10. Used as value10 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value10 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value11opt*Initial value 11. Used as value11 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value11 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value12opt*Initial value 12. Used as value12 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value12 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value13opt*Initial value 13. Used as value13 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value13 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value14opt*Initial value 14. Used as value14 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value14 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value15opt*Initial value 15. Used as value15 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value15 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value16opt*Initial value 16. Used as value16 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value16 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value17opt*Initial value 17. Used as value17 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value17 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value18opt*Initial value 18. Used as value18 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value18 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value19opt*Initial value 19. Used as value19 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value19 to carry back. Optional, but required if the downstream node cannot accept a missing value.
initial value20opt*Initial value 20. Used as value20 on the first round, before any feed-back arrives. Wire the same kind of data you expect LoopEnd value20 to carry back. Optional, but required if the downstream node cannot accept a missing value.
_ezfeed1opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed2opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed3opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed4opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed5opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed6opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed7opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed8opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed9opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed10opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed11opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed12opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed13opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed14opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed15opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed16opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed17opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed18opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed19opt*Internal feed-back slot written by the loop expander. Not a canvas port.
_ezfeed20opt*Internal feed-back slot written by the loop expander. Not a canvas port.

Outputs (21)

NameTypeDescription
indexINT—
value1*—
value2*—
value3*—
value4*—
value5*—
value6*—
value7*—
value8*—
value9*—
value10*—
value11*—
value12*—
value13*—
value14*—
value15*—
value16*—
value17*—
value18*—
value19*—
value20*—