You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Collect node whose only inputs come from an iterator over an empty collection (zero iterations) is never materialized during graph execution. As a result:
the collector and everything downstream of it never run, and
GraphExecutionState.next() returns None while GraphExecutionState.is_complete() keeps returning False.
The session is effectively stalled: there is nothing left to execute, but the graph is never reported as complete.
This is a pre-existing issue (reproduces on current main) and is independent of PR #9343 — that PR was verified to neither introduce nor fix this behavior.
Root cause (analysis)
An iterator over an empty collection produces zero prepared execution nodes, so its source node is never added to executed (a source is only marked executed once all of its prepared exec nodes have completed, and there are none).
_ExecutionMaterializer.prepare() only selects a node for expansion when no ancestor IterateInvocation is still un-executed. Because the empty iterator is never marked executed, the downstream Collect node is never selected.
Consequently no collector exec node is created, its downstream consumer is never enqueued, and since is_complete() requires every source node to be in executed, the state can never complete.
Relevant code: invokeai/app/services/shared/graph.py — the prepare() selection guard (skips nodes with un-executed iterator ancestors) and the collector branch of prepare().
An empty upstream collection should not stall the session. Either:
the Collect node produces an empty collection ([]) and its downstream consumer runs with an empty input, or
the graph is otherwise explicitly reported as complete.
In all cases is_complete() must eventually become True (or an error must be raised) once next() returns None.
Actual behavior
Collect (and its downstream consumer) are never materialized.
next() returns None, but is_complete() stays False indefinitely.
Notes
Reproduces on main (6ca505fe64fd1deed744dca1ec209324ac894e82 and later).
Discovered while reviewing PR Fix nested collector iteration scope #9343 (nested collector iteration scoping). That PR rewrites the collector branch of prepare() but does not change this behavior; the stall exists identically with and without it, so it should be fixed separately.
Summary
A
Collectnode whose only inputs come from an iterator over an empty collection (zero iterations) is never materialized during graph execution. As a result:GraphExecutionState.next()returnsNonewhileGraphExecutionState.is_complete()keeps returningFalse.The session is effectively stalled: there is nothing left to execute, but the graph is never reported as complete.
This is a pre-existing issue (reproduces on current
main) and is independent of PR #9343 — that PR was verified to neither introduce nor fix this behavior.Root cause (analysis)
executed(a source is only marked executed once all of its prepared exec nodes have completed, and there are none)._ExecutionMaterializer.prepare()only selects a node for expansion when no ancestorIterateInvocationis still un-executed. Because the empty iterator is never marked executed, the downstreamCollectnode is never selected.is_complete()requires every source node to be inexecuted, the state can never complete.Relevant code:
invokeai/app/services/shared/graph.py— theprepare()selection guard (skips nodes with un-executed iterator ancestors) and the collector branch ofprepare().Steps to reproduce (minimal, unit-test level)
Graph shape:
Expected behavior
An empty upstream collection should not stall the session. Either:
Collectnode produces an empty collection ([]) and its downstream consumer runs with an empty input, orIn all cases
is_complete()must eventually becomeTrue(or an error must be raised) oncenext()returnsNone.Actual behavior
Collect(and its downstream consumer) are never materialized.next()returnsNone, butis_complete()staysFalseindefinitely.Notes
main(6ca505fe64fd1deed744dca1ec209324ac894e82and later).prepare()but does not change this behavior; the stall exists identically with and without it, so it should be fixed separately.