{"record":{"id":"03fc75c862756a21","repo":"langchain-ai/langchain","slug":"node-with-id-id-already-exists","errorCode":null,"errorMessage":"Node with id {id} already exists","messagePattern":"Node with id (.+?) already exists","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/runnables/graph.py","lineNumber":336,"sourceCode":"        *,\n        metadata: dict[str, Any] | None = None,\n    ) -> Node:\n        \"\"\"Add a node to the graph and return it.\n\n        Args:\n            data: The data of the node.\n            id: The id of the node.\n            metadata: Optional metadata for the node.\n\n        Returns:\n            The node that was added to the graph.\n\n        Raises:\n            ValueError: If a node with the same id already exists.\n        \"\"\"\n        if id is not None and id in self.nodes:\n            msg = f\"Node with id {id} already exists\"\n            raise ValueError(msg)\n        id_ = id or self.next_id()\n        node = Node(id=id_, data=data, metadata=metadata, name=node_data_str(id_, data))\n        self.nodes[node.id] = node\n        return node\n\n    def remove_node(self, node: Node) -> None:\n        \"\"\"Remove a node from the graph and all edges connected to it.\n\n        Args:\n            node: The node to remove.\n        \"\"\"\n        self.nodes.pop(node.id)\n        self.edges = [\n            edge for edge in self.edges if node.id not in {edge.source, edge.target}\n        ]\n\n    def add_edge(\n        self,","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/runnables/graph.py#L318-L354","documentation":"`Graph.add_node` in `langchain_core.runnables.graph` rejects adding a node whose explicit `id` collides with an id already present in `self.nodes`, raising `ValueError`. Ids must be unique within a graph because edges reference nodes by id.","triggerScenarios":"Calling `graph.add_node(data=..., id=0)` twice with the same id; programmatically generated graphs reusing loop indices as ids across iterations; merging subgraphs manually where prefixed ids were expected to differ but the prefix was empty (`Graph.extend` with `prefix=\"\"`), then re-adding nodes.","commonSituations":"Custom visualization or introspection code that walks a runnable and builds a `Graph` by hand; copying example code that adds start/end nodes with fixed ids inside a loop; calling `.add_node()` on nodes already inserted via `extend()` using overlapping numeric ids (since auto-generated `next_id()` counts up, explicit low ids easily collide).","solutions":["Omit the `id` argument and let `graph.next_id()` assign a fresh id.","Namespace explicit ids uniquely (e.g. `f\"{prefix}_{i}\"`) when adding nodes in loops or after `extend()`.","Before adding, check `if node_id in graph.nodes:` and either reuse the existing node or pick a new id."],"exampleFix":"# before\nfor step in steps:\n    graph.add_node(data=step, id=0)  # same id each loop\n\n# after\nfor step in steps:\n    graph.add_node(data=step)  # auto id via next_id()","handlingStrategy":"validation","validationCode":"if node_id in graph.nodes:\n    node = graph.nodes[node_id]  # reuse\nelse:\n    node = graph.add_node(data=data, id=node_id)","typeGuard":null,"tryCatchPattern":"try:\n    node = graph.add_node(data=data, id=nid)\nexcept ValueError as e:\n    if \"already exists\" in str(e):\n        node = graph.nodes[nid]\n    else:\n        raise","preventionTips":["Let next_id() assign ids unless uniqueness is guaranteed.","Namespace explicit ids (prefix_index) in loops and after extend().","Check membership in graph.nodes before re-adding."],"tags":["graph","value-error","visualization","langchain-core"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}