⏪ Cycle Finish
Where ComfyUI Caches State for the Next Queue Run
- CYCLE
- data
- aux
- aux2
- aux3
- aux4
- aux5
- index
- FINISHED?
Cycle End (⏪ Cycle Finish, from ControlFlowUtils) is the closing bracket of the pack's Cycle family - and it's the node that does the actual remembering. Cycle opens the loop, Cycle Continue carries your data through processing, and Cycle End caches the result back into the loop state so the next prompt run picks it up. It's the difference between "generate an image" and "generate an image, then queue again to refine that image."
It's deceptively small: one required input, a few optional ones, two outputs. But it's the node that makes multi-run progressive workflows possible.
The inputs that matter
- CYCLE (required) - connect to a Cycle node's CYCLE output. This is the state dict the whole loop lives in.
- data (required) - the value to cache for the next iteration. This is your pipeline's payload: an image, a latent, a prompt string, whatever you want to survive into the next queue run.
- aux, aux2–aux5 - additional cargo, same behavior. Use them for secondary data like a seed or a filename.
On the way out you get two things:
- index - the loop counter after step is applied. Wire this somewhere if you want to know which iteration you're on (or feed it into a filename).
- FINISHED? - a boolean that's
Trueonce the counter has reached end. This is your "stop the machine" signal - pair it with this pack's Halt Execution node so an Auto-Queue cycle doesn't loop forever.
How the caching works
Mechanically, Cycle End takes whatever you feed into data/aux and stuffs it into the CYCLE state dictionary, then bumps the counter by step. On the next prompt execution, Cycle Continue reads that same dict and hands the cached values back out as its data/aux outputs - which you process and send right back into Cycle End. Round and round, one queue run per lap.
Two behaviors you'll hit almost immediately:
The dry run. The very first execution of a cycle returns (None, None) from Cycle End - index and FINISHED? are both None because nothing has been cached yet and the counter hasn't started. That first pass exists so the workflow can initialize. If you ignore it, your first real run will be confused about what's None; handle it via the Cycle node's RESET? output instead.
Auto-reset. If the Cycle's auto_reset is on (the default), reaching end wraps the counter back to start and keeps cycling - but note the index output at that point still reflects the step that just ran. If you need the loop to actually stop, the counter reaching end is your cue to halt execution rather than let it wrap.
Also worth knowing: the state lives in the running ComfyUI process. Restart ComfyUI and the cycle resets to its first dry run; leave it running and a cycle you "finished" last week may resume with last week's data. That persistence is the whole point of the node - it's also the pack's documented known issue, so when in doubt, restart.
Install
Cycle End ships in VykosX/ControlFlowUtils:
# ComfyUI Manager → Install Custom Nodes → search "ControlFlowUtils"
# or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/VykosX/ControlFlowUtils
Restart and it's under 🐺 VykosX-ControlFlowUtils, grouped with Cycle and Cycle Continue. No dependencies. If you're setting up your first cycle, grab the "Simple Cycle Workflow" from the repo - it's the fastest way to see the data round-trip actually working.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| CYCLE | CYCLE | Connect to the CYCLE output of a [Cycle] node to establish a loop | |
| data | * | Any data you wish to iterate on and propagate to subsequent prompts | |
| auxopt | * | Any optional Auxiliary data you wish to iterate on and propagate to subsequent prompts | |
| aux2opt | * | Any optional Auxiliary data you wish to iterate on and propagate to subsequent prompts | |
| aux3opt | * | Any optional Auxiliary data you wish to iterate on and propagate to subsequent prompts | |
| aux4opt | * | Any optional Auxiliary data you wish to iterate on and propagate to subsequent prompts | |
| aux5opt | * | Any optional Auxiliary data you wish to iterate on and propagate to subsequent prompts |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| index | INT | The Index of the loop counter after being incremented or decremented by Step |
| FINISHED? | BOOLEAN | Boolean value that specifies whether the cycle has terminated |