{"record":{"id":"bd78a621ca6d6cfe","repo":"langchain-ai/langchain","slug":"recursion-limit-reached-when-invoking-self-with-bd78a6","errorCode":null,"errorMessage":"Recursion limit reached when invoking {self} with input {final}.","messagePattern":"Recursion limit reached when invoking (.+?) with input (.+?)\\.","errorType":"exception","errorClass":"RecursionError","httpStatus":null,"severity":"critical","filePath":"libs/core/langchain_core/runnables/base.py","lineNumber":5393,"sourceCode":"                    output = chunk\n                else:\n                    try:\n                        output = output + chunk\n                    except TypeError:\n                        output = chunk\n        else:\n            output = call_func_with_variable_args(\n                self.func, final, config, run_manager, **kwargs\n            )\n\n        # If the output is a Runnable, use its stream output\n        if isinstance(output, Runnable):\n            recursion_limit = config[\"recursion_limit\"]\n            if recursion_limit <= 0:\n                msg = (\n                    f\"Recursion limit reached when invoking {self} with input {final}.\"\n                )\n                raise RecursionError(msg)\n            for chunk in output.stream(\n                final,\n                patch_config(\n                    config,\n                    callbacks=run_manager.get_child(),\n                    recursion_limit=recursion_limit - 1,\n                ),\n            ):\n                yield chunk\n        elif not inspect.isgeneratorfunction(self.func):\n            # Otherwise, just yield it\n            yield cast(\"Output\", output)\n\n    @override\n    def transform(\n        self,\n        input: Iterator[Input],\n        config: RunnableConfig | None = None,","sourceCodeStart":5375,"sourceCodeEnd":5411,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/runnables/base.py#L5375-L5411","documentation":"In `RunnableLambda._transform` (sync streaming), if the function's output is itself a `Runnable`, the lambda streams from that runnable with `recursion_limit - 1`; at limit 0 a `RecursionError` is raised. This bounds sync streaming pipelines where lambdas keep returning runnables, mirroring the invoke-path guard.","triggerScenarios":"A generator-function lambda yielding a `Runnable` as a chunk; `stream()` on a chain whose lambda returns a runnable that returns a runnable, deeper than `recursion_limit`; explicit low `recursion_limit` in streaming config.","commonSituations":"Streaming routers that hand off to the next runnable per chunk; migrating invoke-based delegation code to `stream()` and keeping infinite hand-off; deep streaming chains exceeding the default limit.","solutions":["Terminate delegation: invoke/absorb the returned runnable inside the lambda instead of returning it.","Raise `recursion_limit`: `chain.stream(x, config={'recursion_limit': 100})`.","Model the hand-off as an explicit sequence or loop rather than nested runnable returns.","Verify each level's output type — only return a `Runnable` when you intend transparent delegation."],"exampleFix":"# before\nfn = RunnableLambda(lambda chunks: (yield next_runnable))  # yields a Runnable\n\n# after\nfn = RunnableLambda(lambda chunks: (yield from next_runnable.stream(consume(chunks))))","handlingStrategy":"validation","validationCode":"def stream_bounded(chain, x, max_depth: int = 50):\n    yield from chain.stream(x, config={'recursion_limit': max_depth})","typeGuard":null,"tryCatchPattern":"try:\n    for chunk in chain.stream(x):\n        yield chunk\nexcept RecursionError as e:\n    if 'Recursion limit reached' in str(e):\n        yield from chain.stream(x, config={'recursion_limit': 100})\n    else:\n        raise","preventionTips":["Yield data chunks, not Runnable objects, from streaming lambdas.","Stream from inner runnables explicitly rather than returning them.","Bound recursion_limit for streaming chains with known depth."],"tags":["runnable","runnable-lambda","streaming","recursion"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}