Skip to content

Workflow: a step whose parent can never reach a terminal status is silently left NOT_STARTED #24223

Description

@thomtrp

Split out of #24136 (fix for #24060), where both shapes came up but neither is caused by that change.

A step is only evaluated when a parent that reached a terminal status enqueues it, and it can only decide once every parent is terminal. So a parent that can never terminate leaves the child stuck at NOT_STARTED forever. Nothing reports it: the run has no running or pending step left, so it ends COMPLETED with part of the graph untouched.

Two ways to get such a parent.

A cycle inside a branch that was not taken

If/Else A
  ├ (if)   → taken
  └ (else) → X → Y → X

Take the if branch. X's parents are the If/Else (dead, since the branch was not taken) and Y. Y's only parent is X. Neither can move. Both end NOT_STARTED and the run reports COMPLETED.

Nothing rejects a cycle: assertWorkflowConnectionOrThrow only checks the handles are defined, and neither createStepEdge nor the workflow validation utils do an acyclicity check, so the edge can be drawn in the editor.

shouldExecuteIteratorStep already solves exactly this for loops by filtering stepIdsInLoop out of the parents it considers. The same idea generalises: a parent that is a descendant of the step is a back edge and must not block it. In an acyclic graph that filter changes nothing, so it only affects the broken case.

A step made unreachable by graph editing that still points at a live step

deleteStepEdge does no reachability check, and a step that loses its last incoming edge stays on the canvas and keeps its own nextStepIds. It can never run, so any step it points at can never conclude. This one already misbehaves on main.

Here the back-edge filter does not help; it needs the executor to treat a parent that is unreachable from the trigger as dead, or the builder to stop producing the shape.

Both need a user to draw an unusual graph, which is why they were left out of #24136.

Metadata

Metadata

Type

No type

Fields

Priority

None yet

Dev status

None yet

Start date

None yet

Target date

None yet

Quarter

None yet

Projects

Status
In project

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions