Leaderboard
Javascript Jun 19, 2026
Javascript Recursive Factorial Infinite Loop Bug

JavaScript Recursion — Spot the Bug in this Factorial!

This is a daily Javascript challenge from the CodeShot archive. Practice your knowledge of Recursive Factorial Infinite Loop Bug and improve your technical interview readiness.

function factorial(n) {
  if (n === 0) return 1
  return n * factorial(n)
}
A The base case should be n === 1
B factorial(n) should be factorial(n - 1) — missing decrement causes infinite loop
C return 1 should be return 0
D n should be a string

Detailed Explanation

Why This Question Matters

Recursion is one of those concepts that feels like a magic trick when you first see it. You’re telling a function to call itself, which sounds like a recipe for an infinite loop. Most developers "get" the theory—the base case and the recursive step—but the actual implementation is where things usually fall apart.

This specific bug is a classic. It's not a syntax error; the code looks clean and follows the general structure of a factorial function. But if you run this in a browser or Node.js, it won't give you a number. It'll crash your tab or throw a RangeError: Maximum call stack size exceeded.

Understanding why this happens is the difference between someone who can copy-paste a recursive pattern and someone who actually understands how the call stack works.

Understanding the Code

Let's look at the snippet:

function factorial(n) {
  if (n === 0) return 1
  return n * factorial(n)
}

On the surface, it looks okay. We have a base case (n === 0) to stop the recursion, and we have the recursive call. But there's a massive flaw in the return statement: return n * factorial(n).

Here is what happens internally when you call factorial(3):

1. The function checks if 3 === 0. It's not.
2. It moves to the next line: return 3 * factorial(3).
3. To solve this, it calls factorial(3) again.
4. Inside that second call, it checks if 3 === 0. Still no.
5. It calls factorial(3) *again*.

The value of n never changes. We aren't moving toward the base case. We're just calling the exact same function with the exact same argument over and over. In programming, this is a recursive loop that never terminates. The JavaScript engine keeps pushing these calls onto the stack until it runs out of memory and crashes.

Finding the Correct Answer

To fix this, we need to ensure that each recursive call brings us one step closer to the base case. That means we need to decrement n.

The correct version should be:
return n * factorial(n - 1)

Why this works:
If we call factorial(3) now, the chain looks like this:
- 3 * factorial(2)
- 3 * (2 * factorial(1))
- 3 * (2 * (1 * factorial(0)))
- 3 * (2 * (1 * 1)) $\rightarrow$ 6

By subtracting 1 in each call, we eventually hit 0, which triggers the return 1 statement. This "unwinds" the stack, multiplying the numbers back up to the top.

If you were looking at multiple-choice options and Option B suggested changing factorial(n) to factorial(n - 1), that's the winner. Any option that doesn't change the argument passed to the recursive call is just going to cause a stack overflow.

Common Mistakes Developers Make

When writing recursive functions, I see a few recurring patterns of failure:

1. Missing the Base Case: Forgetting the if (n === 0) entirely. Without a stop condition, you're just orbiting a black hole of function calls.
2. The "Off-by-One" Error: Setting the base case to n === 1 but not handling 0, or vice versa. This can lead to unexpected results or infinite loops if the input is negative.
3. Ignoring Negative Numbers: If you pass -1 into the fixed version of this function, it will still crash. Why? Because n will go -1, -2, -3... and will never hit 0. In a real project, you'd want a guard clause: if (n < 0) return undefined; or throw an error.
4. Overusing Recursion: Some devs try to use recursion for everything. In JavaScript, recursion can be expensive because each call adds a frame to the stack. For a simple factorial, a for loop is actually more performant and safer.

Real-World Usage

You won't often write a factorial function in a production app, but you will use recursion constantly for tree-like structures.

Think about a file system (folders inside folders) or a DOM tree in the browser. If you need to find a specific nested element or calculate the total size of a directory, a loop isn't enough because you don't know how deep the nesting goes.

A recursive function is the perfect tool here: "Process this folder, and if it contains other folders, call this same function on them." The "base case" in that scenario is simply reaching a folder that has no more sub-folders.

Key Takeaways

- Progress is mandatory: A recursive function must move toward its base case with every call. If the arguments don't change, you're just creating a crash.
- Guard your inputs: Always consider edge cases like negative numbers or null values that might bypass your base case.
- Watch the stack: Remember that JS has a limit on how deep your recursion can go. For massive datasets, consider an iterative approach (loops) or tail-call optimization if the environment supports it.
- Think in layers: Recursion is about breaking a big problem into a smaller version of the same problem.

Why this matters

Understanding Recursive Factorial Infinite Loop Bug is crucial for passing technical interviews. In real-world applications, this concept often leads to subtle bugs if not handled correctly. For more details, you can always refer to the official MDN Documentation.

📝
Reviewed by CodeShot Editorial
Every challenge is code-reviewed by senior developers to ensure accuracy and real-world relevance. Learn more.

Ready for your shot?

Join thousands of developers solving one logic puzzle every morning.

Solve Today's Challenge →