invoke-ai/InvokeAI · error · InvalidEdgeError
One or both nodes don't exist ({edge})
Error message
One or both nodes don't exist ({edge}) What it means
InvalidEdgeError raised by _get_edge_nodes() when either the source or destination node of an edge cannot be found (NodeNotFoundError). It converts the low-level lookup failure into an edge-level validation error naming the edge. Called by edge validators that need both endpoint nodes.
Source
Thrown at invokeai/app/services/shared/graph.py:1917
InvalidEdgeError,
):
return False
except Exception as e:
raise UnknownGraphValidationError(f"Problem validating graph {e}") from e
def _is_destination_field_Any(self, edge: Edge) -> bool:
"""Checks if the destination field for an edge is of type typing.Any"""
return get_input_field_type(self.get_node(edge.destination.node_id), edge.destination.field) == Any
def _is_destination_field_list_of_Any(self, edge: Edge) -> bool:
"""Checks if the destination field for an edge is of type typing.Any"""
return get_input_field_type(self.get_node(edge.destination.node_id), edge.destination.field) == list[Any]
def _get_edge_nodes(self, edge: Edge) -> tuple[BaseInvocation, BaseInvocation]:
try:
return self.get_node(edge.source.node_id), self.get_node(edge.destination.node_id)
except NodeNotFoundError:
raise InvalidEdgeError(f"One or both nodes don't exist ({edge})")
def _validate_edge_destination_uniqueness(self, edge: Edge, destination_node: BaseInvocation) -> None:
input_edges = self._get_input_edges(edge.destination.node_id, edge.destination.field)
if len(input_edges) > 0 and (
not isinstance(destination_node, CollectInvocation) or edge.destination.field != ITEM_FIELD
):
raise InvalidEdgeError(f"Edge already exists ({edge})")
def _validate_edge_would_not_create_cycle(self, edge: Edge) -> None:
graph = self.nx_graph_flat()
graph.add_edge(edge.source.node_id, edge.destination.node_id)
if not nx.is_directed_acyclic_graph(graph):
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(View on GitHub (pinned to 0b6a024f2f)
Solutions
- Add the missing node to the graph before creating the edge
- Delete dangling edges referencing the removed node
- Verify node id strings match exactly (they are case/whitespace sensitive)
- Run validate_self() on deserialized workflows to surface dangling edges early
Example fix
// before
g.add_edge("res_1", "image", "save_1", "image") # save_1 not added
// after
g.add_node(save_image_node) # id "save_1"
g.add_edge("res_1", "image", "save_1", "image") Defensive patterns
Strategy: validation
Validate before calling
def edge_nodes_exist(graph, edge) -> bool:
return (
edge.source.node_id in graph.nodes
and edge.destination.node_id in graph.nodes
)
assert all(edge_nodes_exist(g, e) for e in g.edges), "dangling edges present" Type guard
def is_connectable(graph, source_id: str, dest_id: str) -> bool:
return source_id in graph.nodes and dest_id in graph.nodes Try / catch
from invokeai.app.services.shared.graph import InvalidEdgeError
try:
g.add_edge(src, "image", dst, "image")
except InvalidEdgeError as e:
if "don't exist" in str(e):
add_missing_nodes_and_retry()
raise Prevention
- Always add nodes before edges when building graphs programmatically
- When deleting a node, delete its edges in the same operation
- Check for dangling edges (edge endpoints not in graph.nodes) after loading JSON
When it happens
Trigger: Adding or validating an edge whose edge.source.node_id or edge.destination.node_id is not present in graph.nodes — e.g. g.add_edge(a, "image", b, "image") where b was never added, or after removing a node while its edges remain.
Common situations: Hand-built graphs where a node was forgotten, deleting nodes without deleting their edges (hand-edited JSON), wrong node id strings, subgraphs referenced with mismatched ids.
Related errors
- The selected saved workflow must contain exactly one workflo
- Edge source and target types do not match ({edge})
- Edge already exists ({edge})
- Edge creates a cycle in the graph ({edge})
- Field types are incompatible ({edge})
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/2630bd566b039cb3.
Report an issue: GitHub.