RangeError: Maximum Call Stack Size Exceeded

RangeError: Maximum Call Stack Size Exceeded

Have you ever encountered this error in JavaScript? And you ask, what does this mean? In this article, you will find the answers to questions like: What is the call stack? Why do I have this error? How can I solve this?

Prerequisites

  • A working knowledge of JavaScript (beginner-level works as I will explain everything in simple and great details such that anyone can understand).

What is The Call Stack

The call stack is a stack data structure that stores information about active subroutine(s). The call stack is also known as the execution stack, program stack, or run-time stack and can simply be called "the stack".

Subroutine is a function, subprogram, or method that is called to perform a specific task or a set of tasks.

A stack is an abstract data type that serves as a collection of elements. You can relate the stack data type to a stack of physical objects like a stack of books or a stack of plates.

As stated earlier, the call stack is a data structure that contains and monitors active function(s) from the point they are called till execution is complete. Functions are added to the call stack using the LIFO pattern (i.e. last in, first out), meaning that the last function added is executed first. Let's see an example of how the call stack works:

function sayHello() {
    console.log("Hello")
}

sayHello()

visual representation of the call stack

When the function sayHello( ) is declared the call stack is empty and the function will only be added to the call stack when it is active i.e. invoked or called. When the function is done with execution it is removed from the call stack. For a function to complete execution it means that;

  • A return statement is encountered exiting the function or

  • All lines in the function have been executed

This explains how the call stack keeps track of active functions.

Furthermore, let's see how the call stack handles multiple function calls keeping in mind that execution occurs using the LIFO pattern.

function greeting() {
    function sayHello() {
        console.log("Hello")
    }

    function sayName() {
        console.log("My name is Sam")
    }

    sayHello()
    sayName()

    console.log("greetings, my name is Sam")
}

greeting()

// Hello
// My name is Sam
// greetings, my name is Sam

In the code above, we declared a function greeting(). Inside that function, we declared two functions namely: sayHello() and sayName(). Both functions are called, then the statement console.log("greetings, my name is Sam").

visual representation of the call stack

This is a visual representation of what happens in the call stack:

  • the call stack is empty before execution of any function.

  • when greeting() is executed it is added to the call stack.

  • in greeting(), when sayHello() is executed, it is added to the call stack(above greeting() in the call stack because it is yet to complete execution).

  • on completion, sayHello() logs "Hello" to the console and is removed from the call stack.

  • sayName() is executed and added to the call stack.

  • on completion, sayName() logs "My name is Sam" to the console and is removed from the call stack.

  • greeting(), continues execution, and logs "greetings, my name is Sam" to the console. On completion, it is removed from the call stack.

This is how the call stack monitors active functions, however, the call stack has a maximum size. When the size of active functions is more than the call stack can take you get the maximum call stack exceeded error.

Maximum Call Stack Size Exceeded

Exceeding call stack size happens when a function keeps calling itself or multiple functions within a function, without a condition to terminate such execution.

A process in which a function calls itself is known as Recursion.

//recursive function in javascript
function recall() {
    console.log("Hello world")
    recall();
}

recall()

//Hello world - first call
//Hello world - second call
//Hello world - third call
//until max, then error.

In the code above, we have a recursive function recall( ) (i.e. the function recall( ) calls itself). The function contains a console.log("Hello world") statement after which it calls itself.

On execution, recall( ) is added to the call stack, "Hello world" is logged to the console, and then recall( ) is executed again and added to the call stack as the active function:

recursive function in the call stack

Now we have two active functions in the call stack. The second recall( ) follows the same process as the first one and executes recall( ) again.

Therefore, a third recall( ) is added to the call stack. The action is repeated continuously until the call stack exceeds the maximum size of functions it can take then, you get the maximum call stack size exceeded error.

How to Avoid the Maximum Call Stack Size Error

If you encounter this error during the execution of a recursive function, it is a clear indication that a crucial part of your code known as the base case is missing.

The Base Case is a condition that terminates recursive calls.

function recall(x) {
  console.log("start")
  x++
  // BASE CASE
  if(x < 5) {
    recall(x)
  }
  console.log("end");
}

recall(1)

// start
// start
// start
// start
// end
// end
// end
// end

The base case here is that "if x is no longer lesser than 5 terminate the recursion!". When the function is called, the following happens:

  • recall(x) is added to the call stack.

  • Then we log "start" to the console.

  • We increase the value of x by 1.

  • We check if x is less than 5. If the condition is true, we call the recall(x) again.

Now the call stack has the two recall(x) calls.

This process continues until the condition i.e. the base case if ( x < 5 ) is false:

Since the condition is false, the function does not call itself, hence the next line of code is executed, and "end" is logged to the console. Then, the function execution is completed. And the fourth recall(x) is removed from the call stack.

Therefore, the third recall(x) continues from where it stopped, executes the next line and "end" is logged to the console, indicating that the execution is completed. After this, the third recall(x) is removed from the call stack.

The second recall(x) continues from where it stopped, repeating the same process as the third recall(x) and is removed from the call stack once execution is completed.

This process continues until the first recall(x) completes execution and the call stack is empty.

Conclusion

The call stack monitors the active function or functions. When you encounter the error "Maximum call stack size exceeded" it is a clear indication we have more active functions than the call stack can take.

Identifying these function(s) and controlling the execution in your code is a good way to avoid the maximum call stack exceeded error.

I genuinely hope you have learnt a thing or two about the call stack. Thank you for reading. Please do well to like and share this article with someone who could learn from it.