Maximum call stack size exceeded - How to Fix (2026)
What is Maximum Call Stack Size Exceeded?
This error occurs when the call stack (the structure that stores function calls) exceeds its maximum size. This typically happens with infinite recursion or very deep function call chains.
Error Message:
RangeError: Maximum call stack size exceeded
Common Causes
Quick Fix (TL;DR)
// ❌ Problem - Infinite recursion
function countdown(n) {
console.log(n);
countdown(n - 1); // No base case!
}
// ✅ Solution - Add base case
function countdown(n) {
if (n <= 0) return; // Base case
console.log(n);
countdown(n - 1);
}
// ✅ Solution - Use iteration instead
function countdown(n) {
for (let i = n; i > 0; i--) {
console.log(i);
}
}
Common Scenarios & Solutions
Scenario 1: Missing Base Case in Recursion
The most common cause - recursive function without a stopping condition.
// Factorial without base case
function factorial(n) {
return n * factorial(n - 1); // Infinite recursion!
}
factorial(5); // RangeError: Maximum call stack size exceeded
// Add base case
function factorial(n) {
if (n <= 1) return 1; // Base case
return n * factorial(n - 1);
}
factorial(5); // 120
// Or use iteration (better for performance)
function factorial(n) {
let result = 1;
for (let i = 2; i <= n; i++) {
result *= i;
}
return result;
}
Scenario 2: Circular Function Calls
Two or more functions calling each other in a loop.
function isEven(n) {
if (n === 0) return true;
return isOdd(n - 1);
}
function isOdd(n) {
if (n === 0) return false;
return isEven(n - 1);
}
isEven(-1); // Infinite loop! Never reaches base case
// Add validation for negative numbers
function isEven(n) {
n = Math.abs(n); // Handle negative numbers
if (n === 0) return true;
return isOdd(n - 1);
}
function isOdd(n) {
n = Math.abs(n); // Handle negative numbers
if (n === 0) return false;
return isEven(n - 1);
}
// Or use simple modulo (better)
function isEven(n) {
return n % 2 === 0;
}
function isOdd(n) {
return n % 2 !== 0;
}
Scenario 3: Event Listener Triggering Itself
Event handlers that trigger the same event they're listening to.
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log('Button clicked');
button.click(); // Triggers itself infinitely!
});
// Solution 1: Remove the recursive call
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log('Button clicked');
// Don't trigger click again
});
// Solution 2: Use a flag to prevent recursion
let isProcessing = false;
button.addEventListener('click', function() {
if (isProcessing) return;
isProcessing = true;
console.log('Button clicked');
// Do your work
isProcessing = false;
});
// Solution 3: Remove listener before triggering
function handleClick() {
console.log('Button clicked');
button.removeEventListener('click', handleClick);
button.click(); // Now safe
button.addEventListener('click', handleClick);
}
button.addEventListener('click', handleClick);
Scenario 4: Deep Recursion with Large Data
Recursion works but the dataset is too large for the call stack.
// Sum array recursively
function sumArray(arr) {
if (arr.length === 0) return 0;
return arr[0] + sumArray(arr.slice(1));
}
const largeArray = new Array(100000).fill(1);
sumArray(largeArray); // RangeError: Maximum call stack size exceeded
// Solution 1: Use iteration
function sumArray(arr) {
let sum = 0;
for (let num of arr) {
sum += num;
}
return sum;
}
// Solution 2: Use reduce
function sumArray(arr) {
return arr.reduce((sum, num) => sum + num, 0);
}
// Solution 3: Tail recursion with trampoline (advanced)
function sumArray(arr, sum = 0) {
if (arr.length === 0) return sum;
return () => sumArray(arr.slice(1), sum + arr[0]);
}
function trampoline(fn) {
while (typeof fn === 'function') {
fn = fn();
}
return fn;
}
const largeArray = new Array(100000).fill(1);
trampoline(sumArray(largeArray)); // Works!
Scenario 5: React setState in Render
In React, calling setState during render causes infinite loop.
function Counter() {
const [count, setCount] = useState(0);
// ❌ setState in render causes infinite loop
setCount(count + 1);
return {count};
}
// Solution 1: Move setState to event handler
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
return (
{count}
);
}
// Solution 2: Use useEffect for side effects
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
// Safe to call setState here
setCount(1);
}, []); // Empty dependency array = run once
return {count};
}
Best Practices to Avoid Stack Overflow
Related Errors
Key Takeaways
- Stack overflow occurs when call stack exceeds maximum size
- Most common cause is infinite recursion without base case
- Always add stopping condition to recursive functions
- Prefer iteration over recursion for large datasets
- Event listeners can cause infinite loops if they trigger themselves
- In React, never call setState during render
Frequently Asked Questions
Level Up Your Javascript Skills
Master Javascript with these hand-picked resources
10,000+ learners
Free forever
Updated 2026
Related JavaScript Topics