invoke-ai/InvokeAI · error · NodeAlreadyExecutedError
Destination node {edge.destination.node_id} has already been
Error message
Destination node {edge.destination.node_id} has already been prepared or executed and cannot have a source edge deleted What it means
GraphExecution.delete_edge throws NodeAlreadyExecutedError when the edge's destination node has already been prepared or executed. Removing an edge to an executed node would invalidate recorded execution results, so it is blocked. Delete edges only before the graph runs.
Source
Thrown at invokeai/app/services/shared/graph.py:2874
self.graph.update_node(node_id, new_node)
def delete_node(self, node_id: str) -> None:
if not self._is_node_updatable(node_id):
raise NodeAlreadyExecutedError(
f"Node {node_id} has already been prepared or executed and cannot be deleted"
)
self.graph.delete_node(node_id)
def add_edge(self, edge: Edge) -> None:
if not self._is_node_updatable(edge.destination.node_id):
raise NodeAlreadyExecutedError(
f"Destination node {edge.destination.node_id} has already been prepared or executed and cannot be linked to"
)
self.graph.add_edge(edge)
def delete_edge(self, edge: Edge) -> None:
if not self._is_node_updatable(edge.destination.node_id):
raise NodeAlreadyExecutedError(
f"Destination node {edge.destination.node_id} has already been prepared or executed and cannot have a source edge deleted"
)
self.graph.delete_edge(edge)
View on GitHub (pinned to 0b6a024f2f)
Solutions
- Remove the edge before the graph is queued for execution
- Copy the graph, delete the edge on the copy, and enqueue the new graph
- Catch NodeAlreadyExecutedError and treat the edge as already-locked
- Check _is_node_updatable(edge.destination.node_id) before delete_edge
Example fix
// before
execution.delete_edge(edge) # raises if destination already executed
// after
if execution._is_node_updatable(edge.destination.node_id):
execution.delete_edge(edge) Defensive patterns
Strategy: validation
Validate before calling
if not execution._is_node_updatable(edge.destination.node_id):
return # edge is locked to an executed node
execution.delete_edge(edge) Type guard
def edge_deletable(execution, edge: Edge) -> bool:
return execution._is_node_updatable(edge.destination.node_id) Try / catch
try:
execution.delete_edge(edge)
except NodeAlreadyExecutedError as e:
logger.info("edge locked: %s", e) Prevention
- Clean up edges before execution starts
- Treat executed graphs as read-only
- Requeue modified copies instead of editing live sessions
When it happens
Trigger: Calling GraphExecution.delete_edge(edge) where edge.destination.node_id has already been prepared or executed.
Common situations: Live graph editing via the UI/websocket during a run, cleanup code that removes stale edges after execution, or re-running an old queue item's session object.
Related errors
- Destination node {edge.destination.node_id} has already been
- Edge source node {edge.source.node_id} does not exist in the
- Edge destination node {edge.destination.node_id} does not ex
- Edge source field {edge.source.field} does not exist in node
- Edge destination field {edge.destination.field} does not exi
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/7bbaed269e7fb1ca.
Report an issue: GitHub.