How to fix RangeError: Maximum call stack size exceeded (infinite recursion) in Node.js

Node.jsINTERMEDIATEHIGHUpdated Dec 9, 2025· 155 views

This error occurs when a function calls itself recursively without a proper base case or termination condition, exhausting the call stack. Stack overflow can also happen during deep object operations, circular event listeners, or when processing deeply nested data structures.

Quick fix

Fixes RANGE_ERROR

RangeError: Maximum call stack size exceeded
  at calculateFactorial (script.js:5:3)
  at calculateFactorial (script.js:6:3)
  at calculateFactorial (script.js:6:3)
  at calculateFactorial (script.js:6:3)
  ...repeated thousands of times...
  1. Identify the function causing the stack overflow
  2. Add a proper base case to recursive functions
  3. Replace recursion with iteration when processing large datasets
  4. Fix event listener infinite loops
node.js — error
RangeError: Maximum call stack size exceeded
at calculateFactorial (script.js:5:3)
at calculateFactorial (script.js:6:3)
at calculateFactorial (script.js:6:3)
at calculateFactorial (script.js:6:3)
...repeated thousands of times...
RangeError: Maximum call stack size exceeded (infinite recursion)

What this error means

A stack overflow happens when the call stack (a limited memory area that tracks function calls) becomes full. Every time a function is called, a new frame is added to the stack. In Node.js, there is a hard limit to how many frames can exist at once (typically around 10,000-30,000 depending on the system). When this limit is exceeded, the JavaScript engine throws a RangeError. This usually indicates infinite recursion where a function keeps calling itself without a way to stop, but can also result from deeply nested callback chains, circular event emissions, or operations on very large/deeply nested objects. The stack overflow indicates a bug in your code logic rather than a system resource shortage.

Typical symptoms

  • Application crashes immediately with "RangeError: Maximum call stack size exceeded"
  • Error appears to happen during a specific operation or function call
  • Stack trace is very long and shows the same function repeating
  • Performance suddenly drops before the crash (due to excessive function calls)
  • Recursive function calls grow without visible progress
  • Event listeners trigger themselves in an infinite loop
  • Deep object cloning or serialization operations fail

Common causes

  1. Recursive function missing base case or termination condition
  2. Recursive function base case never being reached due to logic error
  3. Event emitter triggering its own listener, creating infinite recursion
  4. JSON.stringify() or similar operation on circular or very deeply nested objects
  5. Deeply nested callback chains that don't properly break
  6. Processing arrays or objects with extreme depth without iteration
  7. Promise chaining creating excessive stack depth without proper handling
  8. Mutual recursion between two or more functions without base cases

How to fix "RangeError: Maximum call stack size exceeded (infinite recursion)"

1Identify the function causing the stack overflow

Look at the error stack trace carefully. Stack overflow errors typically show the same function name repeated many times:

bash
RangeError: Maximum call stack size exceeded
  at calculateFactorial (script.js:5:3)
  at calculateFactorial (script.js:6:3)
  at calculateFactorial (script.js:6:3)
  at calculateFactorial (script.js:6:3)
  ...repeated thousands of times...

The function name that repeats is your culprit. In this example, it's calculateFactorial. Run your script with increased logging to trace when the recursion starts:

javascript
let callCount = 0;
function calculateFactorial(n) {
  callCount++;
  console.log(`Call #${callCount}: n=${n}`);
  if (callCount > 100) {
    console.log('Stack overflow detected, exiting early');
    process.exit(1);
  }
  return calculateFactorial(n - 1);
}
2Add a proper base case to recursive functions

Every recursive function MUST have a base case—a condition that stops the recursion. Without it, the function calls itself infinitely.

Before (infinite recursion):

javascript
function countdown(n) {
  console.log(n);
  return countdown(n - 1); // Always calls itself!
}

countdown(5); // RangeError: Maximum call stack size exceeded

After (with base case):

javascript
function countdown(n) {
  if (n === 0) {
    console.log('Done!');
    return; // Base case: stop recursion
  }
  console.log(n);
  return countdown(n - 1);
}

countdown(5); // Logs: 5, 4, 3, 2, 1, Done!

The base case is the if (n === 0) condition. It's the "stopping point" that prevents infinite recursion.

3Replace recursion with iteration when processing large datasets

Recursion consumes stack space for each call. For large datasets, iteration is safer and faster:

Recursive (risky for large arrays):

javascript
function sumArray(arr, index = 0) {
  if (index === arr.length) {
    return 0;
  }
  return arr[index] + sumArray(arr, index + 1);
}

const largeArray = new Array(50000).fill(1);
sumArray(largeArray); // RangeError: stack overflow

Iterative (safe for large arrays):

javascript
function sumArray(arr) {
  let total = 0;
  for (let i = 0; i < arr.length; i++) {
    total += arr[i];
  }
  return total;
}

const largeArray = new Array(50000).fill(1);
console.log(sumArray(largeArray)); // Works fine: 50000

Loops don't add stack frames, so they handle arbitrarily large datasets without overflow.

4Fix event listener infinite loops

If you're emitting an event inside its own listener, you create infinite recursion:

Before (infinite loop):

javascript
const { EventEmitter } = require('events');
const emitter = new EventEmitter();

emitter.on('data', (value) => {
  console.log(value);
  emitter.emit('data', value - 1); // Emits itself!
});

emitter.emit('data', 5); // RangeError

After (with base case):

javascript
const { EventEmitter } = require('events');
const emitter = new EventEmitter();

emitter.on('data', (value) => {
  console.log(value);
  if (value > 0) {
    emitter.emit('data', value - 1);
  }
});

emitter.emit('data', 5); // Logs: 5, 4, 3, 2, 1, 0

Add the termination condition BEFORE emitting the event again.

5Handle deeply nested objects and circular references

JSON.stringify() can fail on deeply nested or circular objects:

Risky code:

javascript
const obj = { value: 1 };
obj.self = obj; // Circular reference!

JSON.stringify(obj); // RangeError: Maximum call stack size exceeded

Solution 1: Use a replacer function:

javascript
const seen = new WeakSet();
const json = JSON.stringify(obj, (key, value) => {
  if (typeof value === 'object' && value !== null) {
    if (seen.has(value)) {
      return '[Circular]'; // Skip circular refs
    }
    seen.add(value);
  }
  return value;
});

Solution 2: Clone objects safely:

javascript
function deepClone(obj, depth = 100) {
  if (depth === 0) {
    console.warn('Max depth reached, truncating object');
    return null;
  }
  if (typeof obj !== 'object' || obj === null) return obj;

  const cloned = Array.isArray(obj) ? [] : {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      cloned[key] = deepClone(obj[key], depth - 1);
    }
  }
  return cloned;
}
6Increase stack size only as a temporary debugging tool

Node.js allows you to increase the stack size temporarily, but this is NOT a fix—only a diagnostic tool:

bash
node --stack-size=2000 script.js

The --stack-size flag sets stack size in kilobytes. This might allow your script to run slightly longer, helping you see where the infinite recursion occurs:

javascript
// Add this at the top of your script
let callCount = 0;
const originalFunc = someFunction;
someFunction = function(...args) {
  callCount++;
  if (callCount % 1000 === 0) {
    console.log(`Made ${callCount} calls so far...`);
  }
  return originalFunc(...args);
};

Use this to identify where the recursion starts spinning, but always fix the underlying logic issue. Increasing stack size is a bandage, not a solution.

Advanced notes

Tail call optimization:
Some languages optimize "tail recursion" (where the recursive call is the last statement). Unfortunately, Node.js/V8 does NOT perform tail call optimization, so even tail-recursive functions will accumulate stack frames. For Node.js, always prefer iteration over recursion for performance-critical loops.

Asynchronous recursion:
Async functions and Promises can also cause stack issues if chained deeply without proper handling:

javascript
// Risky: deeply chained promises
function recursivePromise(n) {
  if (n === 0) return Promise.resolve();
  return Promise.resolve().then(() => recursivePromise(n - 1));
}

recursivePromise(10000); // Can cause stack overflow

Use iteration with async/await instead:

javascript
async function iterativeLoop(count) {
  for (let i = 0; i < count; i++) {
    await somethingAsync();
  }
}

Worker threads for heavy computation:
If you have legitimate deep recursion that can't be refactored to iteration, consider moving it to a Worker thread, which has its own separate stack space.

Debugging tools:
- Use console.trace() to print the call stack at any point
- Enable V8 code coverage to see which functions are called most frequently
- Use Node.js profiler: node --prof script.js followed by node --prof-process to analyze hot functions
- Use the --abort-on-uncaught-exception flag to generate core dumps for analysis

Frequently asked questions

What does "RANGE_ERROR" mean?
A stack overflow happens when the call stack (a limited memory area that tracks function calls) becomes full. Every time a function is called, a new frame is added to the stack. js, there is a hard limit to how many frames can exist at once (typically around 10,000-30,000 depending on the system).
How do I fix "RANGE_ERROR"?
This error occurs when a function calls itself recursively without a proper base case or termination condition, exhausting the call stack. Stack overflow can also happen during deep object operations, circular event listeners, or when processing deeply nested data structures.
What causes "RANGE_ERROR"?
Recursive function missing base case or termination condition Recursive function base case never being reached due to logic error Event emitter triggering its own listener, creating infinite recursion
Is the "RANGE_ERROR" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading