Base Case —
The one line that decides if recursion ever stops.
Every recursive function needs exactly two things: a base case that returns directly with no further recursion, and a recursive case that always moves closer to that base case. Miss either one and the function recurses forever — until Python's stack limit ends it for you. Watch a broken factorial hit that limit on LearnBug, frame by frame.
What is a Base Case?
The condition inside a recursive function that returns a value directly, without calling the function again. It's the only thing that stops the recursion — every recursive call must eventually reach it. The recursive case is everything else: it calls the function again, always with an input that's strictly closer to the base case.
Why visualization helps
A missing or wrong base case doesn't crash immediately — it looks completely normal for the first several hundred calls. LearnBug lets you watch the call stack climb past frame 900, 950, 999 and see the exact moment Python gives up and raises RecursionError, instead of just staring at a traceback after the fact.
Same function, one line different
Correct — has a reachable base case
if n == 1: return 1 — every recursive call passes n - 1, so n strictly decreases and is guaranteed to hit 1 eventually.
Broken — no base case at all
The base case check is missing entirely, so every call always recurses — n decreases toward 1, passes right through it, and keeps going into negative numbers forever.
Also broken — a base case that's never reached
If the recursive case doesn't move toward the base case (e.g. calling factorial(n) instead of factorial(n-1)), the base case exists but is unreachable.
broken_factorial(5) — no base case, watch it run away
broken_factorial(5) calls broken_factorial(4), (3), (2), (1) — looks completely normal so far
For the first several calls, this is indistinguishable from the correct version — every recursive call is legitimately getting closer to what should be the base case.
There's no `if n == 1` check — n=1 just calls broken_factorial(0)
This is the exact moment the bug matters. The correct version would stop here. This one has no check at all, so it keeps recursing straight through the value that should have stopped it.
Stack depth climbs past 900, 950, 999 — every frame identical, none of them returning
The function keeps calling itself with ever-more-negative n. Nothing about any individual call looks different from the last one — the frames are piling up with no end in sight.
Frame ~1000: Python refuses to push another one — RecursionError
Python doesn't detect "this will never stop" — it just runs out of allowed stack depth and raises RecursionError: maximum recursion depth exceeded, unwinding every one of those ~1000 frames as the exception propagates.
Result: RecursionError ✗ — the missing base case, not the logic, is the whole bug
Correct vs broken, side by side
def factorial(n):
if n == 1: # base case — this is what makes it terminate
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120def broken_factorial(n):
# No base case at all! n just keeps decreasing past 1, forever.
return n * broken_factorial(n - 1)
print(broken_factorial(5))
# RecursionError: maximum recursion depth exceededComplexity Notes
Frequently asked questions
Why doesn't Python detect infinite recursion immediately?
Python has no way to know in advance whether a given recursive call will eventually terminate — that's undecidable in general. All it can do is count how many frames are currently active and raise an error once that count crosses a configured limit (about 1000 by default), which is why the crash happens after hundreds of calls, not on the first one.
Is having a base case enough by itself?
No — the base case also has to be reachable. A function like factorial(n) with the correct check if n == 1: return 1 but a recursive call of factorial(n) (forgetting the - 1) has a perfectly valid base case that can never actually be reached, because n never changes. It fails exactly the same way — RecursionError — for a different reason.
Can I just raise Python's recursion limit to avoid this error?
sys.setrecursionlimit() raises the ceiling, but it doesn't fix a genuinely broken base case — it just delays the crash and risks a real stack overflow at the OS level, which can crash the interpreter instead of raising a catchable Python exception. Fix the base case; don't raise the limit to work around it.
How do I check my own recursive function has a correct base case?
Ask two questions: does at least one condition return without recursing (the base case exists), and does every recursive call use an input that's provably closer to that condition (the recursive case makes progress)? If both are true for every possible valid input, the function is guaranteed to terminate.
Watch the stack climb toward the limit — and crash
Paste your own recursive function into LearnBug and see exactly where a missing base case fails.