All nodes/Logic & Flow/Iteration

While Loop

Repeats the loop body while the condition is true. The Start/End ports are pure exec (no data is passed). Done returns the original Input. The optional Status port explains the stop reason: condition_false or max_iterations.

While Loop
InputResult
EndStart
Status

Type in the graph: while_loop

ExecSubgraph

An error branch can be enabled (expose_error_output) to handle failures on their own path.

Ports can be split into separate execution and data handles.

Try it

Repeating with a ceiling

The condition is checked before every pass, the Max Iterations field guards against an endless loop, and the Status port explains the stop.

Entry
While Loop
Log
Exit
  • Execute + Data
  • Execute
Press “Copy nodes”, open the editor and hit Ctrl+V on the canvas.

Runs as pasted

When to use it

Reach for this node when the number of repetitions depends on a condition rather than on a list: poll a job until it is ready, retry until the answer passes a check, refine a model’s result until it is good enough. When the count is the length of a list, use for_each, map or filter instead. Building a loop by hand, with an edge from a branch back up the graph, does not work: the scheduler treats that graph as cyclic and refuses it.

How it works

input (Input) carries the run trigger and a value. start (Start) and end (End) bound the body — they are pure exec ports and carry no data. completed (Done) fires once the loop stops, handing on the value that arrived on input.

The condition is evaluated before every pass, including the first: if it is false right away, the body never runs and completed still fires. The body has to change whatever the condition reads, or the loop runs into the ceiling. Values travel between passes through variables (a var_set node, Session scope) or through {{ nodes.<id>.output }} of a body node.

Passes are bounded twice: by “Max Iterations” and by the engine ceiling, 100 by default. The optional status (Status) port reports why the loop stopped — condition_false or max_iterations — and the same value is available as {{ nodes.<id>.status }}. While the loop runs, {{ variables.loop_index }} holds the current pass, counting from zero.

Common mistakes

  • A condition in mixed form. As with if, {{ counter }} < 5 and {{ flag }} is no longer a single comparison after substitution, and a non-empty string is truthy. Write the whole condition inside {{ }}.
  • A typo in a path gives zero iterations. A missing path renders empty, the condition counts as false, the body is marked “Inside a loop body that never iterated” and the run is reported as successful.
  • A counter on loop_index is off by one. The variable does not exist at the first check, and later it holds the previous pass, so loop_index < 2 gives three passes. For an exact count use “Max Iterations”.
  • Expecting data on the Start port — that edge carries the trigger only.
  • A Thread-scope variable in the condition. Only Session-scope variables appear in {{ variables.<name> }}; read a thread variable through its var node’s output.
  • A loop inside a loop is rejected by the validator.
  • An empty condition will not deploy — the expression is required.

Inputs

PortWirePayloadNotes
InputinputExecute + Dataexecute_data

Execution trigger and payload passed through to Done

EndendExecuteexecute

Outputs

PortWirePayloadNotes
ResultcompletedExecute + Dataexecute_data
StartstartExecuteexecute
StatusstatusDatadata

shown when expose_status = true

Configuration

FieldTypeDefaultDescription
Conditioncondition_expressionstring""

Loop continues while this expression is truthy

supports templates

Expose Status portexpose_statusbooleanfalse

Show a Status data output port carrying the termination reason (condition_false or max_iterations)

Max Iterationsmax_iterationsintegernull

Maximum number of iterations (null = unlimited, bounded by engine cap)

Shared fields

Every node has these three — the platform adds them, not the node author.

  • expose_error_output — When enabled, show an execution output to connect nodes that run if this step fails.
  • split_ports_in — Show separate execution and data input handles instead of one combined port.
  • split_ports_out — Show separate execution and data output handles instead of one combined port.