RecursionError, what it means and how to fix it

Every function call consumes a frame on the call stack, and Python caps the stack (1000 frames by default) to fail loudly instead of crashing. RecursionError means the cap was hit: a function kept calling itself, or a cycle of functions kept calling each other, without ever reaching the case that stops. In practice it is a logic bug, a missing or unreachable base case, far more often than genuinely deep data.

What it looks like

def countdown(n):
    print(n)
    countdown(n - 1)      # no stopping case: calls forever

Traceback (most recent call last):
  File "main.py", line 3, in countdown
RecursionError: maximum recursion depth exceeded

# fixed: give it a base case that is actually reached
def countdown(n):
    if n <= 0:
        return
    print(n)
    countdown(n - 1)

The fix, in order

  1. Verify the base case exists and is reachable. Write down what makes the recursion stop, then check each recursive call moves toward it. The classic bug is a base case the arguments never reach (decrementing by 2 toward an equality test with an odd start, for instance).
  2. Check for accidental self-calls. A property getter that references the property's own name, a __repr__ that formats itself, or a wrapper that calls the function it replaced all recurse without looking recursive.
  3. Print the arguments at each level for a few levels. If the arguments are not changing the way you expect (same object, same value), the progress toward the base case is illusory and the printout shows it.
  4. Convert to a loop when depth is structural. Walking a deep tree, parsing nested data, or processing a long chain is often better as an explicit stack or a plain loop, which has no depth limit at all.
  5. Raise the limit only when the depth is genuinely needed and bounded: sys.setrecursionlimit(10000) plus a larger thread stack (threading.stack_size) for truly deep structures. Raising it to silence an infinite recursion converts a clean exception into a hard interpreter crash.
Do not treat the limit as the bug. The default limit caught an unbounded call pattern. Raising sys.setrecursionlimit without first proving the recursion terminates is how a debuggable error becomes a segfault that kills the whole process.

If it still happens

Mutual recursion (A calls B calls A) with a data-dependent exit can cycle forever on particular inputs, often data with a reference loop (a category whose parent is itself). Validate the input graph for cycles when the recursion follows links in data.

Common questions

What is Python's default recursion limit? 1000 frames, readable with sys.getrecursionlimit(). It counts all nested calls, not just the recursive one, so deep frameworks leave somewhat less room than the number suggests.

Is recursion just bad in Python? No; shallow recursion over naturally recursive data (trees of modest depth, divide and conquer) is clear and safe. Python lacks tail-call optimization, so recursion whose depth grows with input size is the pattern to convert to loops.

Related errors

MemoryError · OverflowError · RuntimeError