invoke-ai/InvokeAI · error · CyclicalGraphError

Graph contains cycles

Error message

Graph contains cycles

What it means

CyclicalGraphError raised by GraphExecution.validate_self() when the flattened networkx graph fails nx.is_directed_acyclic_graph(). InvokeAI graphs must be DAGs because execution order is a topological walk; a cycle means nodes feed each other's inputs with no valid start point. Thrown during graph validation before any node is executed.

Source

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

            if edge.source.field not in source_node.get_output_annotation().model_fields:
                raise NodeFieldNotFoundError(
                    f"Edge source field {edge.source.field} does not exist in node {edge.source.node_id}"
                )

            if edge.destination.field not in type(destination_node).model_fields:
                if isinstance(destination_node, CallSavedWorkflowInvocation) and is_call_saved_workflow_dynamic_input(
                    edge.destination.field
                ):
                    continue
                raise NodeFieldNotFoundError(
                    f"Edge destination field {edge.destination.field} does not exist in node {edge.destination.node_id}"
                )

    def _validate_graph_is_acyclic(self) -> None:
        graph = self.nx_graph_flat()
        if not nx.is_directed_acyclic_graph(graph):
            raise CyclicalGraphError("Graph contains cycles")

    def _validate_edge_type_compatibility(self) -> None:
        for edge in self.edges:
            destination_node = self.get_node(edge.destination.node_id)
            if isinstance(destination_node, CallSavedWorkflowInvocation) and is_call_saved_workflow_dynamic_input(
                edge.destination.field
            ):
                continue
            if not are_connections_compatible(
                self.get_node(edge.source.node_id),
                edge.source.field,
                destination_node,
                edge.destination.field,
            ):
                raise InvalidEdgeError(f"Edge source and target types do not match ({edge})")

    def _validate_special_nodes(self) -> None:
        # TODO: may need to validate all iterators & collectors in subgraphs so edge connections in parent graphs will be available

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Inspect graph.nx_graph_flat() with networkx.find_cycle() to identify the offending node loop
  2. Remove or redirect one edge in the cycle so data flows in a single direction
  3. If the intent was feedback, restructure with CollectInvocation/IterateInvocation nodes or split the node
  4. Validate programmatically with validate_self() before saving or queueing workflows

Example fix

// before
g.add_edge(a, "image", b, "image")
g.add_edge(b, "image", a, "image")  # cycle
// after
g.add_edge(a, "image", b, "image")
g.add_edge(b, "image", c, "image")  # acyclic flow
Defensive patterns

Strategy: validation

Validate before calling

import networkx as nx

def graph_is_acyclic(graph):
    return nx.is_directed_acyclic_graph(graph.nx_graph_flat())

if not graph_is_acyclic(g):
    cycle = nx.find_cycle(g.nx_graph_flat())
    raise ValueError(f"Fix cycle before use: {cycle}")

Type guard

def is_acyclic_graph(graph) -> bool:
    try:
        return nx.is_directed_acyclic_graph(graph.nx_graph_flat())
    except Exception:
        return False

Try / catch

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

try:
    graph.validate_self()
except CyclicalGraphError as e:
    logger.error("cycle detected: %s", e)
    # redirect or drop one edge in the cycle

Prevention

When it happens

Trigger: Adding edges that form a closed loop among existing nodes, then calling graph.validate_self(); deserializing/storing a workflow JSON that contains a cycle (e.g. node A output -> node B input and node B output -> node A input).

Common situations: Hand-edited workflow JSON files, programmatic graph construction with an index/order bug connecting nodes, copy-pasting nodes in the UI and rewiring backwards, or an older workflow schema migrated incorrectly.

Related errors


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