RecursionError: maximum recursion depth exceeded
Python · updated 2026-11-03
Raised when the call stack passes sys.getrecursionlimit(), 1000 by default. The traceback shows the same few lines repeating, often collapsed as "[Previous line repeated 996 more times]"; those lines are the recursion to fix.
Traceback (most recent call last):
File "/app/tree.py", line 30, in <module>
print(depth(root))
File "/app/tree.py", line 6, in depth
return 1 + max(depth(c) for c in node.children)
File "/app/tree.py", line 6, in <genexpr>
return 1 + max(depth(c) for c in node.children)
File "/app/tree.py", line 6, in depth
return 1 + max(depth(c) for c in node.children)
[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceededQuick fix
Read the repeating frames: they name the function. If it never stops, fix the base case or the data (a cycle in a graph, an object that references itself). If the data is legitimately deep, rewrite the recursion as a loop with an explicit stack instead of raising the limit.
- Find the function in the repeated frames of the traceback.
- Check the base case: does every call move toward it?
- For graphs or self-referencing objects, track visited ids so a cycle stops the walk.
- For deep but finite data, convert to an iterative loop with a list as the stack.
- Raise sys.setrecursionlimit only as a last resort and with a modest value.
def depth(root) -> int:
"""Iterative version: no recursion limit, handles cycles."""
best, stack, seen = 0, [(root, 1)], set()
while stack:
node, d = stack.pop()
if id(node) in seen:
continue # cycle: already visited
seen.add(id(node))
best = max(best, d)
stack.extend((c, d + 1) for c in node.children)
return bestWhy it happens
A missing or unreachable base case
A condition that never becomes true (an off-by-one, comparing the wrong field, mutating the wrong variable) makes the function call itself until Python stops it.
A cycle in the data
Walking a graph, a parent and child pair that point at each other, or an ORM object with back-references revisits the same nodes forever without a visited set.
A property or __getattr__ that calls itself
A property that reads self.value inside its own getter, or __getattr__ that touches an attribute that is not set yet, recurses on every access.
Legitimately deep input
Deeply nested JSON, long linked lists or recursive parsers over big inputs can pass 1000 frames even when the code is correct.
Other fixes
- In properties, store the value in a differently named attribute (self._value) to avoid calling the property from itself.
- For JSON that might be deeply nested from untrusted sources, cap nesting depth before parsing it recursively.
- functools.lru_cache does not prevent the error: memoization helps repeated calls, not depth.
Same error, other wording
- RecursionError: maximum recursion depth exceeded while calling a Python object
- RecursionError: maximum recursion depth exceeded in comparison
- RecursionError: maximum recursion depth exceeded while getting the str of an object
Let your coding agent catch the next one
Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:
> Find the RecursionError events in production, show me the function that repeats in each traceback and the input that triggered it, and make it iterative or fix the stop condition.
Related errors
- RangeError: Maximum call stack size exceeded
- KeyError: 'email'
- AttributeError: 'NoneType' object has no attribute 'x'
References: Python docs: RecursionError, Python docs: sys.setrecursionlimit