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
- 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
- If editing workflow JSON by hand, update both the top-level key and the nested node "id" to the same value
- Rebuild the graph programmatically instead of mutating node ids in place
- 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
- Never mutate node.id after inserting a node; use set_node to re-key it
- When editing workflow JSON, keep top-level keys and nested node "id" values identical
- Run graph validation before persisting or executing any programmatically built graph
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
- 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
- denoising_start ({self.denoising_start}) must be less than d
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/da1530f48d59a089.
Report an issue: GitHub.