maximum call stack size exceeded JavaScript [SOLVED]


JavaScript

Author: Steve Alila
Reviewer: Deepak Prasad

The primary cause of the maximum call stack size exceeded error is a recursive function that never terminates. This tutorial takes a deeper dive into the origin of the error and how you can solve it.

You will first understand JavaScript functions. We will then write a recursive function and understand how the call stack handles it. Lastly, we will generate the range error and teach you how to debug and solve it.

Let's get started.

 

Understand JavaScript functions

A function is a code block that performs a specific task. Creating a function is referred to as declaring a function. There are two main types of functions in JavaScript: regular and arrow functions.

// regular function
function regularFunction() {
  // do something
}
// arrow function
const arrowFunction = () => {
  // do something
}

The difference between a regular function and an arrow function is that a regular function is hoisted while an arrow function is not. Simply put, you can call a regular function before declaring it, while that does not happen with an arrow function.

Calling a function makes it start working.

// calling a regular function before declaring it
regularFunction()
function regularFunction() {
  // do something
}

const arrowFunction = () => {
  // do something
}

// calling an arrow function after declaring it
arrowFunction()

A regular or arrow function can be anonymous if it does not have a name. That mainly happens when the function is used as a callback function. A callback function is used as an argument to another.

const button = document.querySelector('button')

button.addEventListener('click', function () {
  // do something
})

button.addEventListener('click', () => {
  // do something
})

The regular function () {} and arrow () => {} functions get called when the click event occurs. Another way to use the callback functions is to declare them elsewhere before referencing them in their callers.

const button = document.querySelector('button')

button.addEventListener('click', regularFunction)
function regularFunction() {
  // do something
}

const arrowFunction = () => {
  // do something
}
button.addEventListener('click', arrowFunction)

We can program a function to run automatically without calling it. The function is then called an immediately invoked function expression (IIFE).

(function anIIFE() {
    // do something
})()

Lastly, a function can call itself. Such a function is said to be recursive.

const factorialOf = (n) => {
    if (n <= 1) return 1
    return n * factorialOf(n-1)
}

console.log(factorialOf(5))

The function factorialOf(n-1) keeps calling itself with a smaller portion of the input n until the input becomes zero. How does that happen? Find out below.

 

What happens when you call a function? Understand JavaScript call stack

Your JavaScript code interacts with the CPU through a browser or runtime environment like Node.js. The browser or Node.js wraps a JavaScript engine.

The JavaScript engine is the interface that determines the interpretation or Just-In-Time compilation of your code. It creates a stack to handle function calls.

The stack receives, runs, and releases a function depending on the calling or urgency order. The engine determines how many times recursion occurs in the stack. The count is called recursion depth.

Each JavaScript engine has its maximum recursion depth. Side effects show when your function exceeds the maximum recursion depth. For example, your browser may freeze or throw a range error with the message, "Maximum call stack size exceeded."

Let's see code examples that could make the call stack to throw the error: Maximum call stack size exceeded.

 

An example of maximum call stack size exceeded error

A recursive function that never terminates is the main origin of the range error: Maximum call stack size exceeded. The function often terminates when it hits a base case: it cannot reduce the input further.

In our Fibonacci implementation, we told the function to stop calling itself when the input's value reduces to 1 or below.

if (n <= 1) return 1

The stopping condition if (n <= 1) return 1 is the base case. What happens when we (forget or) remove the base case?

Let's find out.

Input

const factorialOf = (n) => {
    return n * factorialOf(n-1)
}

console.log(factorialOf(5))

Output

/home/user/GoLinuxCloud/index.js:2
    return n * factorialOf(n-1)
    ^

RangeError: Maximum call stack size exceeded
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:5)
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:16)
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:16)
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:16)
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:16)
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:16)
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:16)
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:16)
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:16)
    at factorialOf (/home/user/GoLinuxCloud/index.js:2:16)

Node.js v18.12.1

We get a range error RangeError: Maximum call stack size exceeded.

Maximum call stack size exceeded error

We can print a cleaner error message or handle the error using try-catch blocks.

input

try {
    const factorialOf = (n) => {
        return n * factorialOf(n-1)
    }
    console.log(factorialOf(5))
} catch (e) {
    console.log("The recursive function FAILED with this error message:", e.message)
}

Output

The recursive function FAILED with this error message: Maximum call stack size exceeded

maximum call stack size exceeded JavaScript [SOLVED]

After catching the exception, we can debug the code using the browser's Dev Tools or the Node.js debugger.

 

Conclusion

The key takeaway from this tutorial is that improperly handled functions could lead to hitting the JavaScript engine's maximum recursion depth. As a result, the call stack throws the range error: RangeError: Maximum call stack size exceeded.

The most immediate solution is to look for recursive functions without bases or debug the code as this tutorial recommends. Alternatively, you can test code in try-catch blocks with unique error messages.

 

Steve Alila

Steve Alila

He specializes in web design, WordPress development, and data analysis, with proficiency in Python, JavaScript, and data extraction tools. Additionally, he excels in web API development, AI integration, and data presentation using Matplotlib and Plotly. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment