invoke-ai/InvokeAI · error · DuplicateNodeIdError

Node ids must be unique, found duplicates {duplicate_node_id

Error message

Node ids must be unique, found duplicates {duplicate_node_ids}

What it means

DuplicateNodeIdError (a ValueError subclass) is raised by Graph._validate_unique_node_ids when two or more node entries share the same node.id during graph validation. Unlike NodeAlreadyInGraphError (raised at add_node time), this is a bulk validation that runs when a graph is validated/loaded as a whole, catching duplicates introduced outside add_node (e.g., via direct dict manipulation or deserialization).

Source

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

        list.extend(self.edges, new_edges)
        for edge in new_edges:
            self._add_edge_to_indexes(edge)

    def delete_edge(self, edge: Edge) -> None:
        """Deletes an edge from a graph"""

        try:
            list.remove(self.edges, edge)
            self._remove_edge_from_indexes(edge)
        except ValueError:
            pass

    def _validate_unique_node_ids(self) -> None:
        node_ids = [n.id for n in self.nodes.values()]
        seen = set()
        duplicate_node_ids = {nid for nid in node_ids if (nid in seen) or seen.add(nid)}
        if duplicate_node_ids:
            raise DuplicateNodeIdError(f"Node ids must be unique, found duplicates {duplicate_node_ids}")

    def _validate_node_id_mapping(self) -> None:
        for node_dict_id, node in self.nodes.items():
            if node_dict_id != node.id:
                raise NodeIdMismatchError(f"Node ids must match, got {node_dict_id} and {node.id}")

    def _validate_edge_nodes_and_fields(self) -> None:
        for edge in self.edges:
            source_node = self.nodes.get(edge.source.node_id, None)
            if source_node is None:
                raise NodeNotFoundError(f"Edge source node {edge.source.node_id} does not exist in the graph")

            destination_node = self.nodes.get(edge.destination.node_id, None)
            if destination_node is None:
                raise NodeNotFoundError(f"Edge destination node {edge.destination.node_id} does not exist in the graph")

            if edge.source.field not in source_node.get_output_annotation().model_fields:
                raise NodeFieldNotFoundError(

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Open the workflow JSON and give each duplicated node a unique id (also updating edge references to it).
  2. Rebuild the graph programmatically via add_node with fresh uuid4 ids instead of constructing the raw dict.
  3. Before validation, run your own dedup: build an id set and rename or drop duplicates plus fix their edges.
  4. If duplicates come from template merging, regenerate ids for the merged-in subgraph nodes and remap edges.

Example fix

// before
graph = Graph(nodes={"n1": node_a, "n1": node_b})  # DuplicateNodeIdError on validate
// after
import uuid
for n in merged_nodes:
    n.id = uuid.uuid4().hex  # remap edges referencing old ids accordingly
    graph.add_node(n)
Defensive patterns

Strategy: validation

Validate before calling

def find_duplicate_node_ids(nodes) -> set:
    seen, dups = set(), set()
    for n in nodes:
        (dups if n.id in seen else seen).add(n.id)
    return dups

dups = find_duplicate_node_ids(nodes)
if dups:
    raise ValueError(f"fix duplicate ids before validating graph: {dups}")

Type guard

def graph_has_unique_node_ids(graph) -> bool:
    ids = [n.id for n in graph.nodes.values()]
    return len(ids) == len(set(ids))

Try / catch

try:
    graph.validate_self()
except DuplicateNodeIdError as e:
    print(e)  # 'Node ids must be unique, found duplicates {...}'
    rename_duplicate_nodes(graph)  # assign fresh uuid4 ids + remap edges
    graph.validate_self()

Prevention

When it happens

Trigger: Validating or instantiating a Graph whose nodes dict (or incoming node list) contains two nodes with equal id values; loading a workflow JSON where copy-paste produced identical node ids; deserializing a graph serialized from concatenated node lists.

Common situations: Hand-edited workflow JSON where a node was duplicated without changing its id; merging saved graphs; scripts that build a raw nodes dict and construct Graph(nodes={...}) bypassing add_node's uniqueness check; version changes where validation now runs on graphs that previously loaded laxly.

Related errors


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