{"record":{"id":"5367ad2fc10ebb03","repo":"langchain-ai/langchain","slug":"runnable-dep-has-no-last-node","errorCode":null,"errorMessage":"Runnable {dep} has no last node","messagePattern":"Runnable (.+?) has no last node","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/runnables/base.py","lineNumber":5109,"sourceCode":"            from langchain_core.runnables.graph import Graph  # noqa: PLC0415\n\n            graph = Graph()\n            input_node = graph.add_node(self.get_input_schema(config))\n            output_node = graph.add_node(self.get_output_schema(config))\n            for dep in deps:\n                dep_graph = dep.get_graph()\n                dep_graph.trim_first_node()\n                dep_graph.trim_last_node()\n                if not dep_graph:\n                    graph.add_edge(input_node, output_node)\n                else:\n                    dep_first_node, dep_last_node = graph.extend(dep_graph)\n                    if not dep_first_node:\n                        msg = f\"Runnable {dep} has no first node\"\n                        raise ValueError(msg)\n                    if not dep_last_node:\n                        msg = f\"Runnable {dep} has no last node\"\n                        raise ValueError(msg)\n                    graph.add_edge(input_node, dep_first_node)\n                    graph.add_edge(dep_last_node, output_node)\n        else:\n            graph = super().get_graph(config)\n\n        return graph\n\n    @override\n    def __eq__(self, other: object) -> bool:\n        if isinstance(other, RunnableLambda):\n            if hasattr(self, \"func\") and hasattr(other, \"func\"):\n                return self.func == other.func\n            if hasattr(self, \"afunc\") and hasattr(other, \"afunc\"):\n                return self.afunc == other.afunc\n            return False\n        return False\n\n    __hash__ = None  # type: ignore[assignment]","sourceCodeStart":5091,"sourceCodeEnd":5127,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/runnables/base.py#L5091-L5127","documentation":"Companion check in `RunnableEachBase.get_graph()`: after extending a dependency's trimmed sub-graph, a last node must exist so an edge can connect to the output schema node. If the dependency graph has a first node but no last node, a `ValueError` is raised. This points to a dependency whose `get_graph()` builds a graph with no terminal node.","triggerScenarios":"A dependency of a `.map()`ed runnable whose hand-built `Graph` never establishes a terminal node (e.g. only edges added, or nodes added in an order the graph cannot resolve), then calling `.get_graph()` on the `RunnableEach`.","commonSituations":"Custom runnables constructing `Graph` objects manually with `add_edge` before `add_node`; partial `get_graph` overrides copied from old examples; graph visualization tooling in notebooks.","solutions":["Simplify the custom `get_graph` to a single node: `g = Graph(); g.add_node('dep', self); return g`.","Ensure the graph ends with a node that has no outgoing edges (a definite terminal).","Test the dependency graph directly: `g = dep.get_graph(); g.trim_first_node(); g.trim_last_node(); assert g.last_node() is not None`.","Wrap the dependency in `RunnableLambda` to get a known-good graph."],"exampleFix":"// before\nclass Dep(Runnable):\n    def get_graph(self, config=None):\n        g = Graph()\n        g.add_edge(g.add_node('a', self), g.add_node('b', self))\n        return g  # may lack a resolvable last node after trims\n\n// after\nclass Dep(Runnable):\n    def get_graph(self, config=None):\n        g = Graph()\n        g.add_node('Dep', self)\n        return g","handlingStrategy":"validation","validationCode":"def dep_has_terminal(dep) -> bool:\n    g = dep.get_graph()\n    g.trim_first_node()\n    return g.last_node() is not None or not g.nodes","typeGuard":null,"tryCatchPattern":"try:\n    g = mapped.get_graph()\nexcept ValueError as e:\n    if 'has no last node' in str(e):\n        # simplify the dep's graph to a single node\n        raise\n    raise","preventionTips":["Build custom graphs ending in a definite terminal node.","Prefer one-node graphs for leaf runnables.","Assert graph.last_node() in custom get_graph tests."],"tags":["runnable","runnable-each","graph","get-graph"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}