RecursionError
Python caps stack depth (1000 frames by default) instead of crashing; hitting the cap nearly always means a base case your input never reaches.
Demo
def digits(n): if n == 0: return 0 return 1 + digits(n // 10) digits(2024)
Positive numbers shrink to 0 in a few steps. Negative ones never do: // rounds toward minus infinity, so -5 // 10 is -1 and -1 // 10 is -1 again — the function calls itself forever until the 1000-frame limit stops it. The base case exists; the input just cannot reach it. The fix is in the pitfalls below.
Constructor
| Name | Type | Required | Description |
|---|---|---|---|
| *args | object | no | The message. The interpreter passes one string; str(e) is that string. |
Attributes
| Attribute | Type | Meaning |
|---|---|---|
| args | tuple | The message tuple — e.g. ('maximum recursion depth exceeded',). |
| __traceback__ | traceback | Very long: the same frame repeated. Python collapses it to "[Previous line repeated N more times]" when printing. |
Common patterns
def digits(n): n = abs(n) count = 1 while n >= 10: n //= 10 count += 1 return count
def walk(root): stack = [root] while stack: node = stack.pop() yield node stack.extend(node.children)
import sys sys.setrecursionlimit(5000)
Examples
Pitfalls
def digits(n): if n == 0: return 0 return 1 + digits(n // 10) digits(-5)
def digits(n): n = abs(n) if n < 10: return 1 return 1 + digits(n // 10) digits(-5)
class Config: def __getattr__(self, name): return self.data[name] Config().port
class Config: def __getattr__(self, name): data = self.__dict__.get('data', {}) if name in data: return data[name] raise AttributeError(name) c = Config() c.data = {'port': 80} c.port
class Point: def __init__(self): self.x = 0 def __setattr__(self, name, value): setattr(self, name, value) Point()
class Point: def __init__(self): self.x = 0 def __setattr__(self, name, value): super().__setattr__(name, value) Point().x
When to use
- Catching it at a boundary to report "input too deeply nested" for untrusted data
- Recognising it in a traceback as "this recursion has no reachable end"
- Using the exception as control flow for normal inputs
- Silencing it with sys.setrecursionlimit(10**6) — the process can segfault instead
- Recursion over unbounded input (linked lists, user-provided nesting) → loop with an explicit stack
Notes
FAQ
Find the frame that repeats in the traceback and ask why the base case is not reached for this input: a missing base case, a step that does not move toward it (negative numbers, odd numbers stepping by 2), or an attribute hook (__getattr__, __setattr__, a property) that calls itself. If the recursion is genuinely deep but finite — walking a big tree or deeply nested data — rewrite it as a loop with an explicit stack.