LangGraphLangGraph 1.2 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
38 small wins to finish your pathNext lesson →

Loops and the recursion limit

An edge can point back to an earlier node, which makes the graph loop. LangGraph caps a run at a set number of steps and raises GraphRecursionError if a loop never ends. The default is large (over ten thousand in LangGraph 1.2), so you usually set recursion_limit yourself.

Last updated: 27 Sep, 2026 · LangGraph 1.2

Looping is how an agent repeats until a job is done: draft, check, redraft. A conditional edge back to the start keeps it going; the same edge returning END stops it. The limit is a safety net for loops that never stop.

Imports and the state

Start with the imports and a state holding one counter. GraphRecursionError is the error LangGraph raises when a run takes too many steps.

python
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START
from langgraph.errors import GraphRecursionError

class State(TypedDict):
    n: int   # a counter the loop keeps raising

The self-looping node

Build a graph with one node whose edge points back to itself. Nothing ever sends the run to END, so it repeats without stopping.

python
builder = StateGraph(State)
builder.add_node("loop", lambda s: {"n": s["n"] + 1})  # add 1 each time
builder.add_edge(START, "loop")
builder.add_edge("loop", "loop")   # edge back to itself: never ends

Catching the limit

Run it inside a try, with a low recursion_limit so the cap is reached at once. LangGraph stops the run and raises GraphRecursionError, which the except catches.

python
try:
    builder.compile().invoke({"n": 0}, {"recursion_limit": 5})  # a low cap to hit it fast
except GraphRecursionError:
    print("hit limit")

The unbounded loop end to end

The same pieces in one file, ready to run.

Example
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START
from langgraph.errors import GraphRecursionError

class State(TypedDict):
    n: int

builder = StateGraph(State)
builder.add_node("loop", lambda s: {"n": s["n"] + 1})
builder.add_edge(START, "loop")
builder.add_edge("loop", "loop")   # points back to itself

try:
    builder.compile().invoke({"n": 0}, {"recursion_limit": 5})
except GraphRecursionError:
    print("hit limit")

Why the loop hit the limit

  • The edge loop → loop sends the run back to the same node forever.
  • Nothing ever ends the loop, so LangGraph stops it at the recursion_limit and raises GraphRecursionError.
  • A real loop ends itself with a conditional edge that returns END once the work is done.

A loop that ends itself

A real loop uses a conditional edge that returns END once a stop condition is met. Here it stops when n reaches 5, so there is no error.

Example
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END

class State(TypedDict):
    n: int

def step(s):          return {"n": s["n"] + 1}
def keep_going(s):    return "step" if s["n"] < 5 else END  # loop back, or stop

b = StateGraph(State)
b.add_node("step", step)
b.add_edge(START, "step")
b.add_conditional_edges("step", keep_going)   # the edge that can end the loop

print(b.compile().invoke({"n": 0})["n"])

Raising the limit

python
graph.invoke({"n": 0}, {"recursion_limit": 100})  # top-level config key
Watch out. Hitting the limit usually means the loop makes no progress, so raising the limit is rarely the fix. Check that some node changes the state toward a stop condition. recursion_limit is a top-level config key, not inside configurable.

Where loops appear

  • The agent loop: call the model, run a tool, call the model again, until it stops asking for tools.
  • Retry-until-valid: redraft until a check passes.
Try it yourself
  • Add a conditional edge from loop that returns END once n reaches 5. Does the error go away?
  • Set recursion_limit to 3 and watch it stop sooner.

Little by little, you're building something great.