RangeError: Maximum call stack size exceeded [SOLVED]
If you would like to understand the “RangeError: Maximum call stack size exceeded” error, read the What is Javascript Call Stack? and What is the call stack size limit? sections.
But if you want to know right away about the possible causes of the error and its solutions, you can go straight to the sections on diagnosis.
Table of Contents
What does “RangeError: Maximum call stack size exceeded” mean?
The “RangeError: Maximum call stack size exceeded” error commonly occurs when a function calls itself indefinitely. This same error in Firefox appears as “InternalError: too much recursion”.
More specifically, this error occurs when a function call exceeds the size of the Call Stack. Now you may be wondering, what is the call stack and what is its limit?
Excellent question! Allow me to explain.
What is the Call Stack in JavaScript?
Other names for the Call Stack are Execution Stack, Control Stack, Function Stack.
When a script executes multiple functions, JavaScript’s call stack is a mechanism for the interpreter to keep track of which function is currently being executed and which functions will be called within that function.
The Call Stack is a LIFO data structure, meaning, “Last In, First Out”.
In a LIFO data structure, the last function pushed to the stack is the first to be called.
Imagine a stack of dishes, in which the dishes are placed one on top of the other. If you want to take one out, the last plate you placed on the stack is the first one you pull off.
What is JavaScript’s call stack size limit?
The call stack size limit depends on the JavaScript engine you are using. If you are curious how many recursive calls a certain JavaScript engine can make, you can run the following code.
let i = 0;
function increment() {
i++;
increment();
}
try {
increment();
} catch (error) {
console.log(`The call stack size limit is ${i}.`);
}
In the version of Chrome browser I’m using the response was 45634
. I run the same code on my computer’s version of Node and get the response of 13962
.
Reason 1: when a function calls itself indefinitely
If you see the error “RangeError: Maximum call stack size exceeded”, there is probably a problem with a recursive function within your code. Specifically, the problem is that the function calls itself indefinitely.
Here’s an example. Can you identify the flaw in the code?
// countDown.js
let count = 10;
function countDown() {
console.log(count);
count--;
countDown();
}
countDown();
If we execute this code we will see the error.
$ node countDown.js
...
-12429
-12430
internal/util/inspect.js:1298
function formatPrimitive(fn, value, ctx) {
^
RangeError: Maximum call stack size exceeded
To fix the error when a function calls itself, we have to specify a condition that causes the function to stop calling itself.
// countDown.js
let count = 10;
function countDown() {
if (count < 0) return; // exit condition
console.log(count);
count--;
countDown();
}
countDown();
Reason 2: with a setter or getter method
// setter.js
class Contact {
constructor() {}
set name(name) {
this.name = name; // Recursive call
}
}
const contact = new Contact();
contact.name = 'Leo';
If we execute this code we will see the error.
$ node setter.js
/Users/leo/Workspace/setter.js:5
this.name = name;
^
RangeError: Maximum call stack size exceeded
In this example, when the setter is activated, it is instructed to do the same thing again: set the same property that it should handle. This causes the function to call itself, over and over again, making it infinitely recursive.
This problem also appears if the same variable is used in the getter.
Here is an example of how the error can occur in a getter method. Can you identify the flaw in the code?
// getter.js
class Contact {
get name(){
return this.name; // Recursive call
}
}
const contact = new Contact();
console.log(contact.name);
If we execute this code we will see the error.
$ node getter.js
/Users/leo/Workspace/getter.js:3
return this.name;
^
RangeError: Maximum call stack size exceeded
at get name [as name] (/Users/leo/Workspace/getter.js:3:17)
The getter name calls itself with this.name
which causes it to continue calling itself indefinitely.
Reason 3: beware of infinite loops
It is possible to generate the Maximum call stack size exceeded error if you have an infinite loop that calls a function.
// infinite-loop.js
function sum(a, b) {
return a + b;
}
for (let i = 6; i > 5; i++) {
const result = sum(i, i);
console.log(result)
}
In this case, the condition i > 5
will always evaluate to true and the loop will continue indefinitely. When you use a loop, whether it’s for
, while
, or any other, be sure to specify an exit condition.
Reason 4: loading the same script or the same library multiple times
The error can occur if you load the same file more than once, for example by loading the jQuery library on the same page multiple times.
If you are programming with the Angular development platform, you could inadvertently do a circular import of a module.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
imports: [
CommonModule,
ModuleTwo
],
})
export class ModuleOne {
}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
imports: [
CommonModule,
ModuleOne
],
})
export class ModuleTwo {
}
Can you identify the circular import? ModuleOne
imports ModuleTwo
and ModuleTwo
imports ModuleOne
.
Make sure you don’t load the same script or the same library multiple times.
The “InternalError: too much recursion” and “RangeError: Maximum call stack size exceeded” errors typically occur when a function calls itself so many times that it exceeds the call stack limit.
To resolve the error, find out the cause and specify a condition that will exit the recursion.