What triggers this error
Python caps the call stack at 1000 frames by default. When a function calls itself β directly or through a chain β and nothing stops it before that cap, you get:
RecursionError: maximum recursion depth exceeded
Four situations cause this almost every time:
- A recursive function with no base case at all
- A base case that exists but is never reached due to a logic bug
- Deeply nested data β JSON trees, XML documents, AST nodes with hundreds of levels
- Accidentally overriding a built-in like
__eq__or__repr__so it calls itself
Reading the traceback
The traceback makes the culprit obvious. The same two or three lines repeat hundreds of times:
File "app.py", line 5, in factorial
return n * factorial(n - 1)
File "app.py", line 5, in factorial
return n * factorial(n - 1)
[Previous line repeated 996 more times]
That repeating line is your problem. The fix depends on why it keeps looping.
Fix 1 β Add or correct the base case
Nine times out of ten, this is the actual problem. Every recursive function needs a condition that stops the chain.
Broken:
def factorial(n):
return n * factorial(n - 1) # never stops
Fixed:
def factorial(n):
if n n) to O(n).
## Fix 5 β Catch accidental self-calls in __repr__ and __eq__
Easy to miss: define `__repr__` and use `f"{self}"` inside it. That format string triggers `__repr__` again. Infinite loop.
BAD β infinite recursion
class Node: def repr(self): return f"Node({self})" # calls repr on self!
GOOD β reference the value, not self
class Node: def init(self, val): self.val = val def repr(self): return f"Node({self.val})"
The same trap exists in `__eq__` and `__hash__`. If either one implicitly calls the other, you'll see the same spiral.
## Verify the fix
Run your function against edge cases β zero, negative inputs, and whatever size was crashing before:
import sys print(sys.getrecursionlimit()) # confirm current limit
result = factorial(999) print(result) # large number, no RecursionError
If you raised the limit, probe near the new boundary
sys.setrecursionlimit(3000) result = factorial(2500) print("OK")
No exception across your full input range means the fix held.
## Quick reference
- **Missing base case** β add the termination condition
- **Correct logic, deep input** β `sys.setrecursionlimit(N)`
- **Production/large data** β rewrite with a loop + explicit stack
- **Repeated subproblems** β add `@lru_cache`
- **Accidental self-call** β check `__repr__`, `__eq__`, `__hash__`

