Types of errors in JavaScript runtime environment you may see often

While writing a program, we sometimes make typos or mistakes and suddenly some alert pops up in the console window which may overwhelm you for a second. It is nothing but an error in your code reported by your language compiler or interpreter. The people who develop a language or runtime engine have had to take care of providing a good interface for error readability to improve the developer experience. This blog is about 7 types of built-in runtime JavaScript errors that developers come across daily.

7 types of built-in errors in JavaScript

  1. Range Error
  2. Reference Error
  3. Syntax Error
  4. Type Error
  5. URI Error
  6. Aggregate Error
  7. Internal Error

Before taking deep dive into any of these built-in error types, let's understand the Error constructor in JavaScript first. Javascript runtime throws an Error object when it fails to interpret any line of code in the program. The good part is it provides an implementation of the Error class to us so that we can create custom error objects by inheriting an Error class and throw our custom exceptions.

Class Error {
  message: string;
  name: string;
  fileName: string;
  lineNumber: int;
  columnNumber: int;
  stack: string;

   constructor(message= '',name, fileName,lineNumber,columnNumber,stack) {
       this.message = message;
       this.name = name;
       this.fileName = fileName;
       this.lineNumber = lineNumber;
       this.columnNumber = columnNumber;
       this.stack = stack;
   }
}

This is the implementation of the Error class in javascript language consist of several properties which is nothing but metadata about the errors that occur in the program. Javascript creates an object of the above class and throws it when it fails to interpret any failure code as shown below.

const error = new Error('Oops! Something Went Wrong.');
throw error;

Whick looks like Capture.PNG

Without further ado, let’s take a look at the types:

RangeError

The range error object is thrown when a value is out of the allowed set of values.

function checkRange(value) {
   if(!(value >= 10 && value <= 20)){
        throw new RangeError("The value must be between  10 and 20.")
   }
}

//call function here
try {
   checkRange(100);
}
catch(error) {
   if (error instanceof RangeError){
     console.log("Range Error occured!")
     console.log(error.message)     // The value must be between  10 and 20.
     console.log(error.name)           // RangeError
     console.log(error.fileName)     // file name in which error occur
     console.log(error.lineNumber) // line no. 3
     console.log(error.stack)           // stacktrace provided by browser
   }
}

When the checkRange() function gets called, if the condition checks whether the value is in a specified range or not, and if not, then it throws RangeError with a text message as an argument. we have enclosed this function call inside try block as it is a traditional way in a javascript to handle error-prone code. If any part of code inside the try block throws an error, then control comes in the next catch block with the error object as an argument to catch(). This error object consists of metadata such as error message, name, file name, line number and stack trace, etc. about the error. This metadata helps in debugging and finding the cause of the issue in the program.

ReferenceError

The reference error object is thrown when a non -declared or non-existent variable is referred by any code.

refer.PNG

SyntaxError

The syntax error object is thrown because of syntactically incorrect code or unintentional use of language keywords. Most often, it occurs because of misspelled keywords in a program.

syntax.PNG

TypeError

The type error object is thrown when operations couldn't continue because of a mismatch of the type of data assigning to a variable.

type.PNG

URIError

The URI error object is thrown when browsers URI handling functions such as encodeURI() and decodeURI() are passed with invalid arguments. These functions are used for UTF-8 encoding and decoding of the input URI. URIError objects are thrown on passing an invalid special character such as '%' as input to such URI handling functions.

const uri = 'https://google.com/?x=images';
const encoded = encodeURI(uri);
console.log(encoded);
// expected output: "https://google.com/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"

try {
  console.log(decodeURI(encoded));
  // expected output: "https://google.com/?x=images"
  decodeURI('%')
  // URIError here
} catch (e) { // catches a malformed URI
  console.error(e);
  console.log(e instanceof URIError)  // true
}

AggregateError

The aggregate error object is thrown when several errors get wrapped in a single error. It is thrown when multiple errors need to be reported by operation. Consider an example, if you are attempting for an exam with 5 subjects, and if you failed in all of the 5 subjects, then you are gone!! you get dropped out of the year and have to appear for a test again next year. An aggregate error occurs in a similar way when multiple errors occur on a single operation and they need to get wrapped in a single error. In JavaScript, AggregateError occurs when we uses Promise.any([]) like below.

let promise1 = new Promise((resolve, reject) => {
  reject('Promise1 failed');
}); 

let promise2 = new Promise((resolve, reject) => {
  reject('Promise2 failed');
});

let promise3 = new Promise((resolve, reject) => {
  reject('Promise3 failed');
});

let promise4 = new Promise((resolve, reject) => {
  reject('Promise4 failed');
});

Promise.any([promise1, promise2, promise3, promise4]).catch((err) => {
  console.error(err);
})

The exception may look like the one below though it is self-explanatory.

Capture1.PNG

You can refer to official docs to learn promises in details.

InternalError

The internal error object is thrown when any function is getting called infinite times because of programming mistakes results in JavaScript throwing an exception such as Maximum call stack size exceeded. Some examples of InternalError are too many switch cases, too many parentheses in regular expression, array initializer too large, too much recursion etc. These error messages are self-explanatory and don't need much explanation. Below code is an example of the "too much recursion" error.

function verify(number){
  verify(number)
}

verify(5)

On calling verify() for the first time, it internally calls the same function repeatedly and turns into infinite function calls. Such code leads to the InternalError exception thrown by JavaScript.

How to throw custom errors?

You may want to define your custom error types deriving from the base Error class (as we discussed above) to be able to throw new CustomError() and use instanceof operator on CustomError to check the kind of error in the exception handler. The below code may result in a cleaner and consistent approach for handling custom errors.

Class CustomError extends Error {
   errorCode: number;

  constructor(foo = '400', ...params) {
    super(...params)
    this.name = 'CustomError'
    this.errorCode= foo
  }
}

try {
  throw new CustomError(403, 'You are late!')
} catch(e) {
  console.error(e.name)    //CustomError
  console.error(e.errorCode)    //403
  console.error(e.message) //You are late!
  console.error(e.stack)   //stacktrace
}

There are some static methods such as Error.captureStackTrace() exist on base class Error that creates the stack for the Error instance.

You can refer to official docs for a list of built-in Error types.

I hope this post will help you debug your code little bit faster :)

I would take this opportunity to thank Tanay Pratap and NeogCamp for motivating me to learn kinds of stuff and sharing it with the community.

If you enjoyed this post, please share it on Twitter or LinkedIn.

Thank you!