LangGraphLangGraph 1.2 · Python 3.10+
Dashboard
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 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 set recursion_limit yourself when you want a runaway loop caught early.

Last updated: 29 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.
  • Catching GraphRecursionError is how a script survives a runaway loop; without the try, the error stops the script.

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 sits at the top level of the config dictionary, not inside the configurable key you meet in the checkpointer lesson.

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
  • In the loop that ends itself, change the stop condition to n < 10 and predict the printed number.
  • Replace the lambda with a function that prints n, set recursion_limit to 3, and count the prints before hit limit.
PreviousCommand

Little by little, you're building something great.