Do not run loop when iterator is skipped (#18964)

When an If/Else branch skips an Iterator step (because the branch wasn't
taken), the executor incorrectly entered the iterator's loop body. This
happened because getNextStepIdsToExecute checked !hasProcessedAllItems
on an undefined result, which evaluated to true, causing it to return
initialLoopStepIds instead of the post-loop nextStepIds.

Fix: Add a !executedStepOutput.shouldSkipStepExecution guard to the
iterator condition in getNextStepIdsToExecute, consistent with the
existing shouldFailSafely guard.
This commit is contained in:
Thomas Trompette
2026-03-25 18:35:58 +01:00
committed by GitHub
parent 511d1bd7ab
commit 6c1db2e7fb
2 changed files with 26 additions and 1 deletions
@@ -529,6 +529,30 @@ describe('WorkflowExecutorWorkspaceService', () => {
});
});
it('should return nextStepIds for a skipped iterator instead of entering the loop', async () => {
const step = {
id: 'iterator-1',
type: WorkflowActionType.ITERATOR,
nextStepIds: ['after-loop'],
settings: {
input: {
initialLoopStepIds: ['loop-step-1'],
},
},
} as WorkflowAction;
const result = await service.getNextStepIdsToExecute({
executedStep: step,
executedStepOutput: {
shouldSkipStepExecution: true,
},
});
expect(result).toEqual({
nextStepIdsToExecute: ['after-loop'],
});
});
it('should return nextStepIdsToFailSafely for all branches when if-else is fail-safe', async () => {
const step = {
id: 'if-else-1',
@@ -253,7 +253,8 @@ export class WorkflowExecutorWorkspaceService {
if (
!iteratorStepResult?.hasProcessedAllItems &&
!executedStepOutput.shouldFailSafely
!executedStepOutput.shouldFailSafely &&
!executedStepOutput.shouldSkipStepExecution
) {
const nextStepIdsToExecute = isString(
executedStep.settings.input.initialLoopStepIds,