TraceDynamics
Python

RecursionError: Maximum Recursion Depth Exceeded in Python

RecursionError: maximum recursion depth exceeded means a function called itself too deeply. Learn the three real causes and how to fix each one.

On this page
  1. What the error means
  2. Cause 1: There is no base case
  3. Cause 2: The recursion is correct, but too deep
  4. Cause 3: Accidental recursion you did not write
  5. The quick fix: raise the limit, carefully
  6. What does not help
  7. A follow-up trap: huge numbers
  8. How deep did you actually get?
  9. Related

Your program ran for a moment and then died with a traceback that ends like this:

Output
  File "/private/tmp/pr/inf.py", line 3, in countdown
    return countdown(n - 1)      # no base case
  [Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded

Python stopped your function because it called itself, and was called again, and again, until it hit a safety limit. This is almost always one of three different problems. Telling them apart is the whole job.

What the error means#

Every function call takes up a frame on Python's call stack, and recursion stacks one frame on top of another. Python caps that depth so a runaway function raises a clean error instead of crashing the process. Check your limit:

Python
import sys
print(sys.getrecursionlimit())
Output
1000

It was 1000 on Python 3.14.5 and on 3.13.15. The line [Previous line repeated 996 more times] in the traceback is Python collapsing the thousands of identical frames so you can read the output.

Cause 1: There is no base case#

The classic bug: a recursive function with no condition that stops it.

Python
def countdown(n):
    return countdown(n - 1)      # never stops

countdown(1000)

Every recursive function needs a branch that returns without calling itself, and every call must move toward that branch. Add the base case:

Python
def countdown(n):
    if n <= 0:
        return
    return countdown(n - 1)

If you see the same line repeated in the traceback and you cannot say when the recursion ends, this is your bug.

Cause 2: The recursion is correct, but too deep#

Sometimes the function is right and the input is simply large. A recursive factorial works up to a point and then fails:

Python
def fact(n):
    return 1 if n <= 1 else n * fact(n - 1)

fact(500)    # fine
fact(5000)   # RecursionError
Output
RecursionError: maximum recursion depth exceeded

The same happens walking a long linked list recursively. We built one with 5,000 nodes:

Output
recursive: RecursionError: maximum recursion depth exceeded

The robust fix is to replace the recursion with a loop:

Python
def total_iter(node):
    s = 0
    while node:
        s += node.v
        node = node.next
    return s
Output
iterative: 12497500

For problems that branch, such as trees and graphs, keep your own explicit stack instead of using the call stack:

Python
def dfs(root):
    stack, seen = [root], []
    while stack:
        node = stack.pop()
        seen.append(node.v)
        if node.next:
            stack.append(node.next)
    return len(seen)
Output
explicit stack visited: 5000

That version has no depth limit, because the "stack" is just a list on the heap. For more on stacks and queues, see Python's deque, and for a recursive algorithm that does stay shallow, quicksort.

Cause 3: Accidental recursion you did not write#

Sometimes there is no obvious recursive call. A property that reads itself is a common culprit:

Python
class User:
    def __init__(self, name):
        self.name = name

    @property
    def name(self):
        return self.name        # reads the property again

    @name.setter
    def name(self, value):
        self._name = value

print(User("ada").name)
Output
  File "/private/tmp/pr/prop.py", line 6, in name
    return self.name        # reads the property again -> forever
           ^^^^^^^^^
  [Previous line repeated 1016 more times]
RecursionError: maximum recursion depth exceeded

self.name is the property, so reading it calls the getter, which reads it again. Store the value under a different name:

Python
@property
def name(self):
    return self._name

The output is then just ada. The same trap exists in __getattr__, __repr__ and __eq__ methods that accidentally call themselves.

The quick fix: raise the limit, carefully#

If the recursion is finite and correct, you can raise the limit:

Python
import sys
sys.setrecursionlimit(10000)

On Python 3.14.5 this worked in our tests. A simple function recursing 5,000 deep succeeded with the limit at 10,000 and 100,000, and failed with it at 3,000:

Output
limit=3000    depth 5000: RecursionError: maximum recursion depth exceeded
limit=10000   depth 5000: 5000
limit=100000  depth 5000: 5000

We could not make the interpreter crash this way on 3.14. The Python documentation still warns that a limit set too high can crash it, and the safe ceiling depends on your platform and Python version. Treat the limit as a safety net, not a tuning knob. It never fixes Cause 1.

What does not help#

functools.lru_cache speeds up repeated work, but it does not reduce depth. A cached recursive Fibonacci still fails once n passes the limit:

Output
RecursionError: maximum recursion depth exceeded

A follow-up trap: huge numbers#

Once you replace a recursive factorial with a loop, you may hit a different error as soon as you print the result:

Output
ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit

Converting a very large integer to text is capped at 4,300 digits by default. You can check the size with x.bit_length() instead, or raise the cap with sys.set_int_max_str_digits(20000).

How deep did you actually get?#

To see the depth your own code reaches before the error:

Python
import sys

def depth(n=0):
    try:
        return depth(n + 1)
    except RecursionError:
        return n

print(depth())
Output
998

With a limit of 1000 we reached 998, because a couple of frames belong to the interpreter itself.

To print what went wrong when you catch an error like this, see printing exceptions in Python. Linked structures that tempt you into deep recursion are covered in reversing a linked list.

Advertisement
esc

↑↓ navigate↵ openesc close