Skip to main content

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__.

Next up in your learning path