/errors/javascript/maximum-call-stack-size-exceeded
Uncaught RangeError: Maximum call stack size exceeded
- tool
- JavaScript
- exit code
- 1
- versions
- ECMAScript 2015+, Node.js 18+, all browsers
- os
- any
RangeError: Maximum call stack size exceeded means a function kept calling itself (directly or through other functions) until the JavaScript engine ran out of stack frames. In V8 (Chrome, Edge, Node.js) the error is a RangeError; Firefox reports the same problem as InternalError: too much recursion. Almost always it is unbounded recursion: a missing base case, a getter that reads its own property, or two functions that call each other. Look at the repeated frame in the stack trace: that is the function to fix.
Reproduce it
A recursive function with no base case, and a getter that returns its own property:
node -e '
function factorial(n) { return n * factorial(n - 1); }
try { factorial(5); } catch (e) { console.log(`${e.name}: ${e.message}`); }
const user = { get name() { return this.name; } };
try { user.name; } catch (e) { console.log(`${e.name}: ${e.message}`); }
'Output
RangeError: Maximum call stack size exceeded RangeError: Maximum call stack size exceeded
Uncaught, Node.js prints the same frame repeated, which points at the culprit:
cat > app.js <<'EOF'
const user = { get name() { return this.name; } };
console.log(user.name);
EOF
node app.js 2>&1 | grep -E "RangeError|at get name" | sort | uniq -c | sed -E 's/^ +[0-9]+ /N× /'Output
N× at get name (/tmp/work/app.js:1:41) N× RangeError: Maximum call stack size exceeded
Fix the recursion
node -e '
function factorial(n) {
if (n <= 1) return 1; // base case
return n * factorial(n - 1);
}
console.log(factorial(5));
class User {
#name; // store the value in a different field
constructor(name) { this.#name = name; }
get name() { return this.#name; }
}
console.log(new User("Ada").name);
'Output
120 Ada
Deep but correct recursion
If the algorithm is right but the input is deep, convert the recursion into a loop with an explicit stack, which lives on the heap and has no frame limit:
function sumTree(root) {
let total = 0;
const stack = [root];
while (stack.length) {
const node = stack.pop();
total += node.value;
stack.push(...node.children);
}
return total;
}Spreading a huge array into a function call fails for a similar reason (each element becomes an argument):
node -e '
const big = Array.from({ length: 1_000_000 }, (_, i) => i);
try { Math.max(...big); } catch (e) { console.log(`${e.name}: ${e.message}`); }
console.log(big.reduce((a, b) => (a > b ? a : b)));
'Output
RangeError: Maximum call stack size exceeded 999999