Skip to content

[bug]: Per-item If over a collected sibling-iterator zip is rejected as UnsupportedIfFramesError #9820

Closed

Description

@lstein

Is there an existing issue for this problem?

  • I have searched the existing issues

Version number

#9789 at e27f6fd. On main (aa46003) the same graph hangs.

What happened

Take an If whose condition is computed per item of an Iterate (left), and whose branch is a Collect of a zipped pair of left and an unrelated right Iterate. With #9789 it fails up front with UnsupportedIfFramesError: If node if combines a condition iterated by left with a branch that may carry frames of the unrelated right.

The graph is well-defined. The zipped Collect closes right's frame, so the branch value is per left item, the same frame as the condition.

What you expected to happen

For left = [1, 2] and the condition left - 1 (true for 2 only), the result should be ["fallback", [12, 22]].

How to reproduce the problem

g = Graph()
g.add_node(CollectionConcatInvocation(id="left_source", first=[1, 2]))
g.add_node(CollectionConcatInvocation(id="right_source", first=[10, 20]))
g.add_node(IterateInvocation(id="left"))
g.add_node(IterateInvocation(id="right"))
g.add_node(AddInvocation(id="body"))
g.add_node(CollectInvocation(id="branch_collect"))
g.add_node(AddInvocation(id="minus_one", b=-1))
g.add_node(FixedCollectionTestInvocation(id="condition"))
g.add_node(AnyTypeTestInvocation(id="fallback", value="fallback"))
g.add_node(IfInvocation(id="if"))
g.add_node(CollectInvocation(id="collect"))
g.add_edge(create_edge("left_source", "collection", "left", "collection"))
g.add_edge(create_edge("right_source", "collection", "right", "collection"))
g.add_edge(create_edge("left", "item", "body", "a"))
g.add_edge(create_edge("right", "item", "body", "b"))
g.add_edge(create_edge("body", "value", "branch_collect", "item"))
g.add_edge(create_edge("left", "item", "minus_one", "a"))
g.add_edge(create_edge("minus_one", "value", "condition", "value"))
g.add_edge(create_edge("condition", "condition", "if", "condition"))
g.add_edge(create_edge("branch_collect", "collection", "if", "true_input"))
g.add_edge(create_edge("fallback", "value", "if", "false_input"))
g.add_edge(create_edge("if", "value", "collect", "item"))

Additional context

_IfActivationController._is_branch_framed uses _ExecutionNodeBuilder._is_iterator_frame_open_at. After a Collect over sibling zipped iterators, that check deliberately counts both sibling frames as still open, because it cannot tell which one the Collect closes. So right looks like an open branch iterator unrelated to the condition's left.

#9789 already computes structural frame depths in _get_frame_depths. Comparing depths, rather than iterator identity, would likely accept this graph and still reject truly unrelated frames.

Found while reviewing #9789.

Activity

  1. JPPhoto commented on Oct 18, 2026

    @JPPhoto
    Collaborator

    Resolved in PR #9843. The reported per-item If over a Collect of sibling Iterate axes now preserves condition-aligned grouped results, including [fallback, [12, 22]]. Regression coverage also checks reordered nodes and empty sibling streams; unsupported divergent axes are rejected explicitly before invocation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions