invoke-ai/InvokeAI · error · InvalidEdgeError

Iterator input type does not match iterator output type ({ed

Error message

Iterator input type does not match iterator output type ({edge}): {err}

What it means

InvalidEdgeError raised by _validate_iterator_edge_rules() when an edge into an IterateInvocation's 'collection' input would break the invariant that the iterator's item output type matches its collection element type. _is_iterator_connection_valid() returns the reason, which is embedded in the message. This runs at add-edge time, before validate_self().

Source

Thrown at invokeai/app/services/shared/graph.py:1948

            raise InvalidEdgeError(f"Edge creates a cycle in the graph ({edge})")

    def _validate_edge_field_compatibility(
        self, edge: Edge, source_node: BaseInvocation, destination_node: BaseInvocation
    ) -> None:
        if isinstance(destination_node, CallSavedWorkflowInvocation) and is_call_saved_workflow_dynamic_input(
            edge.destination.field
        ):
            return
        if not are_connections_compatible(source_node, edge.source.field, destination_node, edge.destination.field):
            raise InvalidEdgeError(f"Field types are incompatible ({edge})")

    def _validate_iterator_edge_rules(
        self, edge: Edge, source_node: BaseInvocation, destination_node: BaseInvocation
    ) -> None:
        if isinstance(destination_node, IterateInvocation) and edge.destination.field == COLLECTION_FIELD:
            err = self._is_iterator_connection_valid(edge.destination.node_id, new_input=edge.source)
            if err is not None:
                raise InvalidEdgeError(f"Iterator input type does not match iterator output type ({edge}): {err}")

        if isinstance(source_node, IterateInvocation) and edge.source.field == ITEM_FIELD:
            err = self._is_iterator_connection_valid(edge.source.node_id, new_output=edge.destination)
            if err is not None:
                raise InvalidEdgeError(f"Iterator output type does not match iterator input type ({edge}): {err}")

    def _validate_collector_edge_rules(
        self,
        edge: Edge,
        source_node: BaseInvocation,
        destination_node: BaseInvocation,
        allow_inputless_source_collector: bool,
    ) -> None:
        if isinstance(destination_node, CollectInvocation) and edge.destination.field in (ITEM_FIELD, COLLECTION_FIELD):
            err = self._is_collector_connection_valid(
                edge.destination.node_id, new_input=edge.source, new_input_field=edge.destination.field
            )
            if err is not None:

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Ensure the edge into 'collection' comes from an output whose type is a list of the expected item type
  2. Adjust the iterator's downstream consumers or upstream source so input and item types agree
  3. Wrap single items in a collect/batch node to produce the expected collection type
  4. Update the custom node pack if its output type changed

Example fix

// before
g.add_edge(prompt, "prompt", iterate, "collection")  # str into collection
// after
g.add_edge(batch_prompt, "collection", iterate, "collection")  # list[str]
Defensive patterns

Strategy: validation

Validate before calling

def iterator_input_ok(graph, iterate_node_id, source) -> bool:
    return graph._is_iterator_connection_valid(
        iterate_node_id, new_input=source
    ) is None

if iterator_input_ok(g, "iterate_1", EdgeSource(node_id="batch_1", field="collection")):
    g.add_edge("batch_1", "collection", "iterate_1", "collection")

Type guard

def is_compatible_iterator_input(graph, iterate_node, source) -> bool:
    if not isinstance(iterate_node, IterateInvocation):
        return False
    return graph._is_iterator_connection_valid(
        iterate_node.id, new_input=source
    ) is None

Try / catch

from invokeai.app.services.shared.graph import InvalidEdgeError

try:
    g.add_edge(src, src_field, iterate, "collection")
except InvalidEdgeError as e:
    if "Iterator input type does not match" in str(e):
        wrap_source_in_batch_node(src)  # emit a proper collection type
    else:
        raise

Prevention

When it happens

Trigger: Calling g.add_edge(x, field, iterate_node, "collection") where x.field's type conflicts with the type the iterator emits as 'item' (checked via _is_iterator_connection_valid with new_input=edge.source).

Common situations: Feeding a non-collection or wrong-element-type output into an iterator, changing the iterator's upstream after downstream consumers were wired for the old item type, hand-edited workflow JSON.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/98d78d7b46e40ce0. Report an issue: GitHub.