{"record":{"id":"2630bd566b039cb3","repo":"invoke-ai/InvokeAI","slug":"one-or-both-nodes-don-t-exist-edge","errorCode":null,"errorMessage":"One or both nodes don't exist ({edge})","messagePattern":"One or both nodes don't exist \\((.+?)\\)","errorType":"validation","errorClass":"InvalidEdgeError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/shared/graph.py","lineNumber":1917,"sourceCode":"            InvalidEdgeError,\n        ):\n            return False\n        except Exception as e:\n            raise UnknownGraphValidationError(f\"Problem validating graph {e}\") from e\n\n    def _is_destination_field_Any(self, edge: Edge) -> bool:\n        \"\"\"Checks if the destination field for an edge is of type typing.Any\"\"\"\n        return get_input_field_type(self.get_node(edge.destination.node_id), edge.destination.field) == Any\n\n    def _is_destination_field_list_of_Any(self, edge: Edge) -> bool:\n        \"\"\"Checks if the destination field for an edge is of type typing.Any\"\"\"\n        return get_input_field_type(self.get_node(edge.destination.node_id), edge.destination.field) == list[Any]\n\n    def _get_edge_nodes(self, edge: Edge) -> tuple[BaseInvocation, BaseInvocation]:\n        try:\n            return self.get_node(edge.source.node_id), self.get_node(edge.destination.node_id)\n        except NodeNotFoundError:\n            raise InvalidEdgeError(f\"One or both nodes don't exist ({edge})\")\n\n    def _validate_edge_destination_uniqueness(self, edge: Edge, destination_node: BaseInvocation) -> None:\n        input_edges = self._get_input_edges(edge.destination.node_id, edge.destination.field)\n        if len(input_edges) > 0 and (\n            not isinstance(destination_node, CollectInvocation) or edge.destination.field != ITEM_FIELD\n        ):\n            raise InvalidEdgeError(f\"Edge already exists ({edge})\")\n\n    def _validate_edge_would_not_create_cycle(self, edge: Edge) -> None:\n        graph = self.nx_graph_flat()\n        graph.add_edge(edge.source.node_id, edge.destination.node_id)\n        if not nx.is_directed_acyclic_graph(graph):\n            raise InvalidEdgeError(f\"Edge creates a cycle in the graph ({edge})\")\n\n    def _validate_edge_field_compatibility(\n        self, edge: Edge, source_node: BaseInvocation, destination_node: BaseInvocation\n    ) -> None:\n        if isinstance(destination_node, CallSavedWorkflowInvocation) and is_call_saved_workflow_dynamic_input(","sourceCodeStart":1899,"sourceCodeEnd":1935,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/shared/graph.py#L1899-L1935","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ng.add_edge(\"res_1\", \"image\", \"save_1\", \"image\")  # save_1 not added\n// after\ng.add_node(save_image_node)  # id \"save_1\"\ng.add_edge(\"res_1\", \"image\", \"save_1\", \"image\")","handlingStrategy":"validation","validationCode":"def edge_nodes_exist(graph, edge) -> bool:\n    return (\n        edge.source.node_id in graph.nodes\n        and edge.destination.node_id in graph.nodes\n    )\n\nassert all(edge_nodes_exist(g, e) for e in g.edges), \"dangling edges present\"","typeGuard":"def is_connectable(graph, source_id: str, dest_id: str) -> bool:\n    return source_id in graph.nodes and dest_id in graph.nodes","tryCatchPattern":"from invokeai.app.services.shared.graph import InvalidEdgeError\n\ntry:\n    g.add_edge(src, \"image\", dst, \"image\")\nexcept InvalidEdgeError as e:\n    if \"don't exist\" in str(e):\n        add_missing_nodes_and_retry()\n    raise","preventionTips":["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"],"tags":["invokeai","graph-validation","missing-node","edges"],"backgroundTag":"node-not-found","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}