The Ultimate Guide to JavaScript Errors
Artur Meyster
Posted on October 15, 2020
The Ultimate Guide to JavaScript Errors
Do you fully understand what an error prompt is communicating when it appears on the screen? Most entry level developers are accustomed to the copy and paste method in attempts to find a quick solution to the error, but understanding the different types of errors thrown, and why they are thrown, makes us better developers and software engineers. We can then begin to understand on a fundamental level what needs to get fixed and what needs debugging.
According to the JavaScript MDN web docs, there are six types of JavaScript errors, seven if we count a warning. In this article, we’ll dive into all of them, include some examples, and explain the difference between a warning and an error.
Error: Permission denied to access property ‘x’
This error occurs when the code is attempting to access an object which it does not have permission to access.
InternalError: too much recursion
This error is triggered when there are too many function calls or when a recursive function is missing a base case. Some programming languages have a limit to how many function calls it can do, so if a function does have a base case, the limit has most likely been exceeded.
RangeErrors
A RangeError occurs when a value is not in the set or range of allowed values. It is usually thrown when you attempt to pass a value as an argument to a function that does not allow a range that includes the value.
Below is an example of a range error when dealing with arrays.
let a = [];
a.length = a.length - 1;
// Uncaught RangeError: Invalid array length
ReferenceErrors
In JavaScript, a reference error is thrown when the code attempts to reference a non-existent variable. According to JavaScript web docs, there are six types of reference errors, with variations of each, that may be triggered in our code. This article focuses on five most common reference error examples for developers.
Undefined variables
Forgetting to define a variable before referencing is a common mistake that triggers the reference error for new developers. This can also happen if the referenced variable is commented out.
let firstName = "John"
let age = 23
console.log(lastName)
// Uncaught ReferenceError: lastName is not defined
let firstName = "John"
let lastName = "Smith"
let age = 23
console.log(lastName)
// returns Smith
Scope
Variables defined inside a function’s scope cannot be accessed outside of it. We can think of scope as laws that govern a country, let’s say the United States. Local laws for the city of San Francisco do not apply in the city of Miami. Miami residents living in Miami must follow Miami laws.
In the function below, we are attempting to access the value outside of its lexical scope.
function nums() {
numA = 1
numB = 2
return numA + numB
}
console.log(numA);
// Uncaught ReferenceError: numA is not defined
We can fix this by defining our variables in a global scope.
numA = 1
numB = 2
function nums() {
return numA + numB
}
console.log(nums());
// returns 3
Strict Mode
Strict Mode intentionally has a different set of semantics than the regular defaulted, “sloppy mode” JavaScript code. A key thing to remember while coding in strict mode is it eliminates silent errors by changing them into throw errors. A JavaScript statement uses strict mode if “use strict”; is invoked before a statement.
function referenceErr(a){
"use strict";
foo = true;
if(a == 0){
return foo
} else {
return !foo
}
}
console.log(referenceErr(1))
// Uncaught ReferenceError: foo is not defined
As JavaScript developers, we know to use var, let, or const to define a variable, but the above example would have been a silent error if strict mode was not invoked.
function referenceErr(a){
"use strict";
let foo = true;
if(a == 0){
return foo
} else {
return !foo
}
}
console.log(referenceErr(1))
// returns false
Redeclarations
Not full understanding how to redeclare variables can also trigger reference errors.
function redeclarations() {
let declare = 1;
if (true) {
let declare = (declare + 1);
}
}
console.log(redeclarations())
// Uncaught ReferenceError: Cannot access 'declare' before initialization
To fix the code above, we must either change “let” to “var” or omit “let” inside our if statement completely.
function redeclarations() {
let declare = 1;
if (true) {
declare = (declare + 1);
}
}
console.log(redeclarations())
SyntaxErrors
Syntax are rules that dictate how programming languages should be written. Each language has its own set of rules with different syntax. We can think of them like grammar or punctuation marks in spoken languages. The question mark in English (?) differs from the question mark in Greek (;).
We can deduce that when we get a syntax error, we are writing our programming language incorrectly. We may either be omitting something accidentally or accidentally using syntax from a different language, which is something that often occurs as developers grow their tech stack.
Common Syntax Errors and How to Fix Them
Brackets
Missing or an overflow of brackets are a cause for common syntax errors. One short can result in a syntax error of an unexpected end of input, one too many can result in an unexpected token.
function errors(a){
if(a > 5){
return true
} else {
return false
// missing closing curly bracket
}
console.log(errors(5))
// Uncaught SyntaxError: Unexpected end of input
function errors(a){
if(a > 5){
return true
} else {
return false
}
}
// one bracket too many below
}
console.log(errors(5))
// Uncaught SyntaxError: Unexpected token '}'
There are several extensions available in VS Code and other text editors that can help you keep track of matched and mismatched brackets to prevent these errors from being thrown. The error in the console will also state what line in the code the error is occurring.
Parentheses
Like brackets, sometimes it can be hard to follow a match to a closing parentheses, or where a parenthese may be needed, like in the parameters of arrow functions.
const errors = a, b => {
if(a + b == 5){
return "equals"
} else if (a + b > 5 ) {
return "greater"
} else {
return "less"
}
}
console.log(errors(1, 2))
// Uncaught SyntaxError: Missing initializer in const declaration
We need to enclose the parameters a and b inside a parentheses to write the syntax of the above function correctly.
Commas
Forgetting commas in objects is another common syntax error trigger.
let student = {
name: "John",
age: 23
location: "Remote"
}
console.log(student.name)
// Uncaught SyntaxError: Unexpected identifier
We need a comma after every key value pair. The fix for the above is putting a comma after 23.
Semicolons
Forgetting semicolons where they are expected, like in for loops, are another common syntax error trigger.
### let arr = [1, 2, 3, 4]
### for(let i =0; i < arr.length i++){
### console.log(arr[i] * 2)
### }
### // Uncaught SyntaxError: Unexpected identifier
Multi-lingual Syntax Confusion
It is very common for developers to use syntax from a different language in JavaScript, either intentionally or by mistake. It is important to be familiar with JavaScript’s own set of rules and be mindful of them when coding.
The below is a common syntax error thrown if Python is the developer’s primary programming language.
let arr = [1, 2, 3, 4]
for(i in length of arr){
console.log(arr[i] * 2)
}
// Uncaught SyntaxError: Unexpected identifier
As JavaScript developers, we code for loops in a different way.
let arr = [1, 2, 3, 4]
for(let i in arr){
console.log(arr[i] * 2)
}
TypeErrors
A TypeError is an object that represents an error as a result of doing an operation that cannot be performed, usually because a value in an operation is not of the expected type.
But what are types? According to the latest version of the JavaScript specifications, ECMAScript, there are nine data and structural types. Six of which – sometimes seven if we count null – are primitive data types, those being string, number, bigint, boolean, undefined, and symbol. Before we can understand why TypeErrors trigger during an operation, let’s review our nine types in JavaScript. If we are ever in a position where we are unsure of how to categorize a type, we can use the typeof operator.
- undefined: A type of value that automatically gets defined to variables that have just been declared. We often get a typeerror value of undefined when we forget to define or add a value to our variable.
- Boolean: Logical data type containing only values of true or false.
- Number: Numeric data type.
- String: Sequence of characters inside backticks, sing, or double quotes.
- BigInt: Numeric data type sometimes known as bignums in other programming languages.
- Symbol: Value that represents a unique identifier created by invoking the Symbol function.
- Object: A structural type and almost anything the ‘new’ keyword is able to create, like an array, object, map, set, etc.
- Function: Another non-data structure that is a code snippet that may be called by other pieces of code.
- null: Usually an intentional value representing an object or address that does not exist.
Most Common JavaScript TypeErrors and How to Fix Them
TypeErrors can be thrown at you when attempting to change a value that cannot be changed or when using a value in an inappropriate way. It can also occur when an argument is passed to a function incompatible with the type expected by the function or the operator inside of the function.
Changing a Value That Cannot be Changed
When you use the const keyword to assign a value to something, this means it is constant, it will not change. Attempting to change the value of a constant variable will result in a TypeError.
const a = 5
a = "5"
// Uncaught TypeError: Assignment to constant variable.
We can fix this by simply changing the name of the identifier we want to identify the string of “5”.
const a = 5
const b = "5"
Using a Value in an Inappropriate Way
Developers must also make sure values are being used as intended. In the example below, “Cat” and “garfield” are backwards when trying to verify if garfield is an instance of the Cat() function.
function Cat() {}
function Dog() {}
let garfield = new Cat()
Cat instanceof garfield
// Uncaught TypeError: Right-hand side of 'instanceof' is not callable
We can fix this by correcting the order of the two.
function Cat() {}
function Dog() {}
let garfield = new Cat()
garfield instanceof Cat
An Argument That is Incompatible with the Type Expected by a Function
When coding an operation, developers have to make use of values for a desired result. The value of null can be used intentionally to signify the absence of an object, but the way in which it is used below will result in a TypeError as it is being used in as an argument incompatible with the type expected by the function.
function readingErrorsAreImportant(a){
if(a.length === 5){
return "equals five"
} else if(a.length > 5) {
return "Greater than five"
} else {
return "Less than five"
}
}
console.log(readingErrorsAreImportant(null))
// Uncaught TypeError: Cannot read property 'length' of null
We can fix this by passing in a value type it is expecting. Like a numeric value type.
function readingErrorsAreImportant(a){
if(a.length === 5){
return "equals five"
} else if(a.length > 5) {
return "Greater than five"
} else {
return "Less than five"
}
}
console.log(readingErrorsAreImportant(10))
URIError
A URI error is an error that occurs when a global URI handling function is used incorrectly, either the encoding or decoding argument wasn’t successful.
Warnings
Unlike errors, warnings will continue to execute your code, but are there to explain to you of potential pitfalls a piece of code may have. There are several different types of warnings that may be thrown, but the important thing to do is fix them when they occur to prevent undesired outcomes in your code later on.
Posted on October 15, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.