🔧 Error Fixes

Maximum Call Stack Size Exceeded — How to Fix It


RangeError: Maximum call stack size exceeded

A function is calling itself (or calling another function that calls it back) infinitely until the call stack runs out of space.

Fix 1: Missing Base Case in Recursion

// ❌ No base case — calls itself forever
function countdown(n) {
  console.log(n);
  countdown(n - 1);
}

// ✅ Add a base case
function countdown(n) {
  if (n <= 0) return;  // Stop here
  console.log(n);
  countdown(n - 1);
}

Fix 2: Infinite useEffect Loop (React)

// ❌ setState triggers re-render, which triggers useEffect, which triggers setState...
useEffect(() => {
  setCount(count + 1);
});

// ✅ Add a dependency array
useEffect(() => {
  setCount(count + 1);
}, []);  // Run once

See also: React too many re-renders fix

Fix 3: Circular JSON.stringify

// ❌ Object references itself
const obj = {};
obj.self = obj;
JSON.stringify(obj);  // 💥 Maximum call stack

// ✅ Use a replacer to handle circular references
function safeStringify(obj) {
  const seen = new WeakSet();
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) return '[Circular]';
      seen.add(value);
    }
    return value;
  });
}

Fix 4: Getter/Setter Calling Itself

// ❌ Getter calls itself
const obj = {
  get name() {
    return this.name;  // 💥 Calls the getter again
  }
};

// ✅ Use a backing property
const obj = {
  _name: 'Alice',
  get name() {
    return this._name;
  }
};

Fix 5: Two Functions Calling Each Other

// ❌ Mutual recursion without termination
function isEven(n) {
  return isOdd(n - 1);
}
function isOdd(n) {
  return isEven(n - 1);
}

// ✅ Add base cases to both
function isEven(n) {
  if (n === 0) return true;
  if (n < 0) return false;
  return isOdd(n - 1);
}
function isOdd(n) {
  if (n === 0) return false;
  if (n < 0) return false;
  return isEven(n - 1);
}

Fix 6: Convert Recursion to Iteration

If your recursion is too deep (even with a base case), convert to a loop:

// ❌ Deep recursion (might overflow for large n)
function factorial(n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}

// ✅ Iterative version
function factorial(n) {
  let result = 1;
  for (let i = 2; i <= n; i++) {
    result *= i;
  }
  return result;
}

Debugging

Add a counter to find the runaway function:

let calls = 0;
function suspect() {
  calls++;
  if (calls > 1000) throw new Error(`Called ${calls} times — probably infinite`);
  // ... rest of function
}