windmill-labs/windmill · error

itered cannot be empty

Error message

itered cannot be empty

What it means

In the Windmill flow executor's while-loop/for-loop module handling, when a loop module is first entered and the iterator produced no items (`iter` is empty), the code panics instead of creating zero flow jobs. Windmill treats an empty iteration set as a modeling error for the loop step at this point, because the loop result structure (flow_jobs_success/duration, new_args) cannot be meaningfully constructed from nothing.

Source

Thrown at backend/windmill-worker/src/worker_flow.rs:5901

            if itered.is_empty() {
                ForLoopStatus::EmptyIterator
            } else if *parallel {
                ForLoopStatus::ParallelIteration { itered_len: itered.len(), itered }
            } else if let Some(first) = itered.first() {
                let iter = Iter { index: 0 as i32, value: first.to_owned() };
                ForLoopStatus::NextIteration(ForloopNextIteration {
                    index: 0,
                    itered_len: itered.len(),
                    itered,
                    flow_jobs: vec![],
                    flow_jobs_success: Some(vec![]),
                    flow_jobs_duration: Some(FlowJobsDuration::new(0)),
                    new_args: iter,
                    while_loop: false,
                })
            } else {
                panic!("itered cannot be empty")
            }
        }

        FlowStatusModule::InProgress {
            iterator: Some(FlowIterator { itered, index, .. }),
            flow_jobs: Some(flow_jobs),
            flow_jobs_success,
            flow_jobs_duration,
            ..
        } if !*parallel => {
            // Read itered from separate table or fallback to JSONB
            let itered = read_itered_from_db(db, flow_job.id, itered).await?;

            let itered_new = if itered.is_empty() {
                // it's possible we need to re-compute the iterator Input Transforms here, in particular if the flow is being restarted inside the loop
                let by_id = if let Some(x) = by_id {
                    x
                } else {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Guard the loop input upstream: add a branch/preprocessor step that skips the loop module when the array is empty.
  2. Check the loop step's iterator expression and fix it so it produces at least one item, or coerce empty to a sentinel (e.g. loop over `items.length ? items : [null]`).
  3. If empty loops should be legal, patch worker_flow.rs to return a completed FlowStatus (zero jobs) instead of panicking when `iter` is empty.
  4. Inspect the flow run logs to see which step produced the empty iterator and fix the producing step.

Example fix

// before
} else {
    panic!("itered cannot be empty")
}
// after
} else {
    // an empty iterator means the loop is trivially done
    return Ok(FlowStatus::WaitingForCompletedJobs(FlowStatusModule::Success {
        flow_jobs_success: Some(vec![]),
        flow_jobs_duration: Some(FlowJobsDuration::new(0)),
        new_args: serde_json::json!([]),
        while_loop: false,
    }));
}
Defensive patterns

Strategy: validation

Validate before calling

// before a for-loop flow step runs, ensure the iterator is non-empty
const items = args.my_list ?? [];
if (!Array.isArray(items) || items.length === 0) {
  throw new Error("loop input must be a non-empty array; skip the loop instead");
}

Type guard

function isNonEmptyArray(v: unknown): v is unknown[] {
  return Array.isArray(v) && v.length > 0;
}

Prevention

When it happens

Trigger: A for-loop flow step whose input array/iterator expression evaluates to an empty list on the first pass (the `FlowStatusModule::InProgress` branch with no prior `itered` items), so `new_args: iter` would be an empty vec and the executor panics with 'itered cannot be empty'.

Common situations: A flow author wired a loop over a list that is empty at runtime (empty DB result, filtered array, optional input absent); a previous step returns `[]` on first run; skip_if or branching makes the source list empty only in some runs.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/80243cf58b242c77. Report an issue: GitHub.