Fix RecursionError in Python
Error Reference
RecursionError: maximum recursion depth exceeded
A function called itself too many times — usually a missing or unreachable base case.
Base cases
Python caps recursion depth (1,000 frames by default) to protect against stack overflow. Hitting the cap almost always means the base case is missing, wrong, or unreachable:
def countdown(n):
print(n)
countdown(n - 1) # RecursionError: never stops
def countdown_fixed(n):
if n < 0: # base case
return
print(n)
countdown_fixed(n - 1)
Check that every input actually converges toward the base case — a classic bug is recursing on n instead of n - 1, or a condition that skips zero.
Iterative rewrites
Python doesn't optimize tail calls, so deep recursion is better expressed as a loop:
def factorial(n):
result = 1
for i in range(2, n + 1):
result *= i
return result
For tree or graph traversal, replace the call stack with an explicit stack:
def walk(node):
stack = [node]
while stack:
current = stack.pop()
print(current.value)
stack.extend(current.children)
Raising the limit
sys.setrecursionlimit buys headroom for genuinely deep but finite recursion — it does not fix an infinite one, and setting it too high can crash the interpreter with a real stack overflow:
import sys
sys.setrecursionlimit(5000) # use sparingly, prefer iteration
The sneaky ones
Recursion errors also come from dunder methods that call themselves indirectly:
class Config:
def __getattr__(self, name):
return self.data[name] # looks up self.data -> __getattr__ -> infinite
The fix is to read from __dict__ directly, which bypasses __getattr__:
class Config:
def __getattr__(self, name):
return self.__dict__['data'][name]
The same trap exists in __repr__ printing self, or property getters that read the property itself instead of the backing attribute.
Frequently Asked Questions
What is the default recursion limit and how do I check it?
CPython defaults to 1,000 frames. sys.getrecursionlimit() shows the current cap. The limit exists because each frame consumes C stack space; without it, runaway recursion would segfault instead of raising a catchable error.
import sys
print(sys.getrecursionlimit()) # 1000
Is it safe to increase the recursion limit?
Moderately — a few thousand frames is usually fine. But the limit only controls Python; the real constraint is the OS thread stack. Set it very high and a deep recursion will crash the process instead of raising RecursionError. If you need more than a few thousand frames, rewrite iteratively.
Why do I get RecursionError from __getattr__ or __repr__?
__getattr__ runs for every missing attribute — if its own body reads a missing attribute, it re-enters itself forever. Similarly, a __repr__ that formats self recursively loops. Access self.__dict__ directly inside __getattr__, and format fields rather than self in __repr__.