{"record":{"id":"f9c276c1037ebd02","repo":"langchain-ai/langchain","slug":"source-node-source-id-not-in-graph","errorCode":null,"errorMessage":"Source node {source.id} not in graph","messagePattern":"Source node (.+?) not in graph","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/runnables/graph.py","lineNumber":376,"sourceCode":"        conditional: bool = False,  # noqa: FBT001,FBT002\n    ) -> Edge:\n        \"\"\"Add an edge to the graph and return it.\n\n        Args:\n            source: The source node of the edge.\n            target: The target node of the edge.\n            data: Optional data associated with the edge.\n            conditional: Whether the edge is conditional.\n\n        Returns:\n            The edge that was added to the graph.\n\n        Raises:\n            ValueError: If the source or target node is not in the graph.\n        \"\"\"\n        if source.id not in self.nodes:\n            msg = f\"Source node {source.id} not in graph\"\n            raise ValueError(msg)\n        if target.id not in self.nodes:\n            msg = f\"Target node {target.id} not in graph\"\n            raise ValueError(msg)\n        edge = Edge(\n            source=source.id, target=target.id, data=data, conditional=conditional\n        )\n        self.edges.append(edge)\n        return edge\n\n    def extend(\n        self, graph: Graph, *, prefix: str = \"\"\n    ) -> tuple[Node | None, Node | None]:\n        \"\"\"Add all nodes and edges from another graph.\n\n        Note this doesn't check for duplicates, nor does it connect the graphs.\n\n        Args:\n            graph: The graph to add.","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/runnables/graph.py#L358-L394","documentation":"`Graph.add_edge` requires that the source node's id already exists in the graph's node table; edges may only connect registered nodes. If `source.id` is not in `self.nodes`, `ValueError` is raised, since an edge pointing at a missing node would corrupt traversal.","triggerScenarios":"Constructing `Edge`/`Node` objects manually and calling `add_edge(node_a, node_b)` before `add_node(node_a)`; using two distinct `Node` instances that conceptually share an id but where only one was added; copying edges from another graph without first extending the nodes.","commonSituations":"Hand-built graphs for `.get_graph()` overrides in custom Runnables; refactoring graph-building code so node insertion moved after edge creation; merging graphs where nodes were prefixed but the edge endpoints were not updated to the prefixed ids.","solutions":["Add both endpoint nodes (`add_node`) before calling `add_edge`.","Reuse the exact `Node` objects returned by `add_node` when creating edges, rather than new Node instances.","When merging graphs, use `Graph.extend(other, prefix=...))` (it wires nodes and edges consistently) instead of manual node/edge copying."],"exampleFix":"# before\ngraph.add_edge(node_a, node_b)  # node_a not added yet\n\n# after\nna = graph.add_node(data=node_a)\nnb = graph.add_node(data=node_b)\ngraph.add_edge(na, nb)","handlingStrategy":"validation","validationCode":"assert source.id in graph.nodes and target.id in graph.nodes\ngraph.add_edge(source, target)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add both nodes before add_edge.","Reuse the Node objects returned by add_node as edge endpoints.","Prefer Graph.extend() for merging instead of manual copying."],"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"}