invoke-ai/InvokeAI · error · NodeIdMismatchError

Node ids must match, got {node_dict_id} and {node.id}

Error message

Node ids must match, got {node_dict_id} and {node.id}

What it means

NodeIdMismatchError is raised during graph validation when the dictionary key under which a node is stored in GraphValidationNodes does not equal the node's own `id` field. InvokeAI graphs store nodes in a dict keyed by node id, so a key/id divergence means the graph is internally inconsistent. The library throws this to catch graphs built or deserialized incorrectly before execution.

Source

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

        """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(
                    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(

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Ensure every node's `id` attribute matches the dict key it is stored under; re-add the node (del + set_node) after changing its id
  2. If editing workflow JSON by hand, update both the top-level key and the nested node "id" to the same value
  3. Rebuild the graph programmatically instead of mutating node ids in place
  4. Catch NodeIdMismatchError and log the two mismatched ids to identify the offending node

Example fix

# before
node.id = "new_id"  # dict still keyed by "old_id"

# after
del graph.nodes["old_id"]
node.id = "new_id"
graph.nodes["new_id"] = node  # or use graph.set_node(node)
Defensive patterns

Strategy: validation

Validate before calling

def check_node_id_mapping(graph):
    for key, node in graph.nodes.items():
        if key != node.id:
            raise ValueError(f"node keyed as {key!r} has id {node.id!r}")
    return True

check_node_id_mapping(graph)  # before submitting graph

Type guard

def has_consistent_id(key: str, node) -> bool:
    return isinstance(node.id, str) and node.id == key

Try / catch

from invokeai.app.services.shared.graph import NodeIdMismatchError
try:
    validate_graph(graph)
except NodeIdMismatchError as e:
    logger.error("graph node id mismatch: %s", e)

Prevention

When it happens

Trigger: Calling GraphValidationNodes (or a validator that runs _validate_node_id_mapping) when a node was inserted into the nodes dict under a key different from the node object's `id` attribute — e.g. mutating `node.id` after insertion, constructing the dict manually, or deserializing a JSON graph where top-level keys were edited without updating each node's `id`.

Common situations: Hand-editing a workflow JSON file (renaming a node key but not the nested "id" field, or vice versa); programmatic graph mutation that changes node.id without re-adding the node; copying node objects between graphs while keeping stale ids.

Related errors


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