Skip to content
AI Agent How-To

Home › Fixes

Fix: LangGraph GraphRecursionError (Recursion Limit Reached)

Beginner ~3 min read Last tested October 2026

Updated 2026-10-15

The error looks like this:

langgraph.errors.GraphRecursionError: Recursion limit of 25 reached without hitting a stop condition.
You can increase the limit by setting the `recursion_limit` config key.

LangGraph counts super-steps (each round of node executions). The default limit is 25. Hitting it means either your task genuinely needs more steps, or, far more often, your graph loops.

Prerequisites

  • A LangGraph graph (e.g. create_react_agent or a custom StateGraph)

Steps

1. Decide: real work or a loop?

Stream the run and watch which nodes repeat:

for chunk in graph.stream({"messages": [("user", "...")]}, stream_mode="updates"):
    print(list(chunk.keys()))

If you see agent → tools → agent → tools ... with the same tool call each time, it’s a loop. Go to step 3.

2. Raise the limit (when the work is real)

recursion_limit goes in the config, not the input:

result = graph.invoke(
    {"messages": [("user", "Research these 10 companies...")]},
    config={"recursion_limit": 60},
)

A common mistake is putting it in the input dict, where it’s ignored.

3. Fix the loop: check your conditional edge

In a custom graph, the router must return END when there are no tool calls:

from langgraph.graph import END

def should_continue(state):
    last = state["messages"][-1]
    return "tools" if getattr(last, "tool_calls", None) else END

builder.add_conditional_edges("agent", should_continue, ["tools", END])

With the prebuilt tools_condition from langgraph.prebuilt, this is handled for you.

4. Fix the loop: make tool results useful

If a tool returns empty or vague output, the model calls it again. Return explicit text (“No results for X; don’t retry”). See Fix: AI agent stuck in a loop.

5. Fail gracefully

from langgraph.errors import GraphRecursionError

try:
    result = graph.invoke(inputs, config={"recursion_limit": 30})
except GraphRecursionError:
    result = {"messages": [("assistant", "Sorry, I couldn't complete that in time.")]}

Common mistakes

Setting recursion_limit on compile(): it’s a run-time config value, passed to invoke/stream.

Raising the limit to 1000 to make the error go away: hides a loop and multiplies cost.

Subgraphs: the config propagates to subgraphs, so a looping subgraph uses up the parent’s budget.