7 Native Errors in JavaScript

Akilesh Rao
JavaScript in Plain English
7 min readOct 4, 2021

--

Time and again, you sit in front of StackOverflow, trying to figure out what exactly happened in your code and why it’s not working. It’s frustrating because most of the time, the reported problem is not always immediately clear. This blog post will help you try to troubleshoot better next time when working with JavaScript. I’ll be going through some common types of JavaScript errors and their source of origin and I hope, it’ll help you debug your code more efficiently, in the future.

I also have a youtube version of this article which you can watch right here.

Most common types of errors in JS

  1. EvalError
  2. RangeError
  3. ReferenceError
  4. SyntaxError
  5. TypeError
  6. URIError
  7. AggregateError

These error types are objects returned by the browser. So anytime you get an error that is one of these types, you’ll be able to use all the properties of that error object. Since these errors inherit properties from the main Error object, you might see similarities between them. The Error object has the following properties that you can make use of in your application

  • message — The message that’s displayed when you get this error.
  • name — The name/type of the error
  • You’ll also see some additional properties, based on the type of the error and also based on the browser that you’re using.

1. EvalError

JavaScript has this global eval() function which was originally used for evaluating JavaScript statements/expressions as strings. So for example,

eval('2 + 2') //  Output: 4

Whenever you get an error, while running this function, it’ll give you an EvalError. Now, if you’ve had some experience with security, you’ll immediately see a red flag here. What if someone passes malicious code as a string inside this function? It will, as expected, be executed by the browser. Since JavaScript supports string expression evaluation out of the box, it’s better not to use the eval function in any of your projects.

EvalError is not used in the current ECMAScript specification, so for the most part, you won’t be coming across this error. But the EvalError object still exists for backward compatibility. MDN literally tells you not to use this.

RangeError

Whenever you try to pass in variables or parameters that are not in a valid range, you get a RangeError. JavaScript has bounds when it comes to all of its data members. For instance, let's say you’re creating an array with some specific length. The maximum number of elements that you can set for an array is 2³² -1. But after that, it goes out of range and you’ll get a RangeError.
If you try to pass in a negative value, it’ll give you the same result.

RangeError for Arrays

Some other common RangeError instances could be,

  • Trying to get 101(or more) digits after a decimal point in a floating-point number.
1.2345.toFixed(2)   //1.23
1.2345.toFixed(101) //RangeError
1.2345.toFixed(-1) //RangeError
  • Repeating a string for more than a specific range using repeat()
"abc".repeat(5)      //abcabcabcabcabc
"abc".repeat(2**28) //RangeError
"abc".repeat(-1) //RangeError

In Chrome, you’ll also get a RangeError if you exceed the call stack limit by running something recursively in an infinite loop. You might get a different error for the same issue, in the case of Firefox or Edge.

ReferenceError

When you try to access a variable that has not yet been declared, you’ll get a ReferenceError. Now there are some caveats when it comes to this type of error so let’s go through them briefly.

function getName(){
console.log("My name is " + name) // "My name is undefined."
}
getName();
var name = "Jack";

Now if you go by the definition of a ReferenceError, we should be getting an error here because the variable is being accessed before its declaration. But we instead get the desired string but “undefined” in place of the name variable. This happens because of Hoisting. I’ve covered hoisting in detail in a separate video so you can check it out.
But basically what happens is, the whole file goes through a creation phase first where all the variables and functions are allocated some memory by the JS engine. The variables when getting memory are also given a placeholder value of “undefined”. So during the actual execution of the file, it’ll have an undefined value and hence it does not throw an error.

Now if I make a small change to the file,

function getName(){
console.log("My name is " + name) // "My name is undefined."
}
getName();
let name = "Jack"; //Changed the declaration from var to let

The variable declaration has been changed from var to let. Now if I run this, I’ll get a reference error for the variable name. This would make you think that variables declared using “let” are not being hoisted. But that's not the case. They also get hoisted, but they are handled more strictly than var declarations. Only when a “let declaration” is fully initialized, will you be able to access them. So anything piece of code before the line, let name =” Jack” will not be able to access the name variable. “const” declarations also work similarly.

Some other common occurrences for this type of error would be,

  • Undefined variables
  • Invalid scope
const sayHello = () => {
let name = "John";
console.log("Hello " + name);
}
sayHello();
console.log(name); //Reference error since name is inside a function scope

TypeError

JS Engine throws a TypeError whenever a variable/parameter is not of a valid(what was expected) type. For instance, try to define a variable x with a value of 10. Now if you try to call it like you would call a function, you’ll get a TypeError.

This, combined with a SyntaxError, is a very common occurrence. If you create a function with a name that’s already been used for a variable or an object in your file, you’ll also get this error. Some other common instances would be

  • Trying to iterate over non-iterable elements(like variables)
let x = 10;
x.map(val => return true) //Error: map() is only for iterables
  • Trying to edit read-only properties
  • Trying to call string methods like toUpperCase/toLowerCase on non-string elements.
  • Trying to reassign const declarations.

URIError

This error occurs when one of the global URI handling functions(decode URI, endcodeURI, encodeURIComponent, decodeURIComponent) is used incorrectly.

encodeURI replaces each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character. So if you’re trying to encode an invalid sequence, you’ll get this error.
In the case of decode URI, if you pass in a malformed URI, it’ll give you this error.

I, personally, have never come across URI-related errors. So I’m assuming this is the case for most of the developers, but if you’re working on specific URI encoding/decoding-related applications, you might want to look more into them.

SyntaxError

This type of error is triggered when you write code that is not syntactically correct(duh). Whenever you run a piece of code, the JavaScript Engine has to convert this code into a machine-understandable format.

  • It will first break down your code and create individual tokens from them. For instance “let x = 10;” will be tokenized to “let”, “x”,“=”, “10”,“;”.
  • After that, it’ll parse these tokens into a tree-like structure, called Abstract Syntax Tree, which is a more regulated representation of your code. There’s an online tool, called AST Explorer, that will let you look at an AST version of your code.

During the parsing phase, if the JS engine finds any tokens that do not conform to its syntax, it’ll throw a SyntaxError. There could be endless instances of this type of error, but we’ll look at some common ones

  • Trying to use reserved keywords as identifiers
let var = 10; // Error; var is reserved for variable declarations
  • Parsing an invalid string to JSON.
JSON.parse('{foo: 1}'); //Invalid string -> JSON
JSON.parse('{"foo": 1}'); // Valid
  • Missing or trailing commas, brackets, parentheses
  • Nameless functions that are not immediately invoked
function () { return 'Hello world';} //invalid
(function () {})(); //valid
  • Uninitialized const declarations
const VALUE; //Error
  • Interchanging “==” which is a test for equality, with “=” which is used for assigning values

There’s, clearly, a lot of ways to make syntactical mistakes. Most of the messages provided by these error objects are pretty straightforward and self-explanatory so resolving them won’t be an issue.

AggregateError

An AggregateError is basically a bunch of errors wrapped together in a single error. So whenever there are multiple errors reported by an operation, this error is returned. The best example of this is when you pass in multiple promises inside a “Promise.any()” and all of those promises get rejected. You get an AggregateError with the actually errors passed in an array.

Promise.any([
Promise.reject(new Error("Error 1")),
Promise.reject(new Error("Error 2")),
Promise.reject(new Error("Error 3"))
]).catch(e => {
console.log(e.name); //"AggregateError"
console.log(e.errors); //[ Error: "Error 1", Error: "Error 2", Error : "Error 3"]
});

Conclusion

These were some of the most common, native errors that you’ll probably see quite frequently. I hope this helps you with your future debugging endeavors. Feel free to add to this list if you think I may have missed something.

If you have any questions regarding this post or anything else, you can put it in the comments or you could just shoot me a DM on my socials mentioned below. Cheers!

LinkedIn
Twitter
Github

More content at plainenglish.io

--

--