## TL;DR
GraphRecursionError means your graph ran more than 25 super-steps without finishing, usually because a conditional edge loops forever. Fix the loop by giving it a termination condition, and only raise the limit via `config={"recursion_limit": 100}` for graphs that are legitimately long.

## Error
```text
GraphRecursionError: Graph recursion limit of 25 reached. This can be caused by a loop in your graph, or by simply having too many steps.
```

## Steps

1. Find the loop. Print the graph and look for conditional edges that point back to an earlier node:
```python
print(app.get_graph().draw_mermaid())
```
Expected output: a diagram of every node and edge. A cycle between two or more nodes is where the loop lives.

2. Check whether the loop is supposed to end. Read the conditional edge's decision function and the state field it depends on:
```python
def decide(state):
    return "retry" if state["errors"] else "done"
```
Expected output: you can see exactly which state value keeps the loop alive. If the state never moves toward the exit condition, thats the bug.

3. Make the loop terminate. Add a counter to the state and bail out after N attempts:
```python
state["attempts"] = state.get("attempts", 0) + 1
if state["attempts"] == 5:
    return "done"
```
Expected output: the graph finishes instead of recursing forever, and you get a final state you can inspect.

4. If the graph is legitimately long (many sequential steps, no cycle), raise the limit in the invoke config:
```python
result = app.invoke(inputs, config={"recursion_limit": 100})
```
Expected output: the run completes without GraphRecursionError. Set it to roughly 2x your expected step count, not 10000.

## When to use
- The graph dies with GraphRecursionError at any limit
- Two or more nodes keep passing control back and forth
- A retry loop (tool calls, self-correction) has no exit counter

## When not to use
- A single node raises its own exception (thats the node's code, not the graph loop)
- The error is about the state schema (thats validation, a different fix)
- You want the graph to run forever on a schedule (use an external scheduler, not an unbounded graph)

## Variant phrasings

### "GraphRecursionError: recursion limit of 50 reached"
Same error, bigger number. Whoever ran it already raised the limit once. Hunt the loop instead of raising it again.

### recursion limit hit inside a subgraph
Subgraphs share the parent's step budget. Check the subgraph for the loop first, then the parent edges around it.

## Why it happens
LangGraph executes nodes in super-steps and caps them at 25 by default as a safety net against infinite loops. Conditional edges that always return to an earlier node burn through the budget fast. Raising the limit treats the symptom; a termination condition treats the cause.

## Edge cases
- A loop that exits on LLM output is fragile: one stubborn model reply restarts the cycle. Always pair it with a hard counter.
- The limit set on `app.invoke` applies per run; streaming with `app.stream` needs the same config passed there too.
- Very deep but legitimate pipelines (50+ sequential nodes) trip the default with no loop at all. Thats the one case where raising the limit is the whole fix.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_EShDSqpImjyQACj_FYwqCQ
