Top 6 JavaScript errors and how developers can fix them

| 8 min. (1632 words)

JavaScript errors are every developer’s nightmare. They’re not just irritating—they can stop your project dead in its tracks. And let’s face it, whether you’re a seasoned pro or just getting started, you’re bound to encounter these mistakes. But why keep tripping over the same issues?

At Raygun, we’ve seen it all when it comes to JavaScript errors, and we know which ones are the real time-wasters. In this guide, we’re not just listing them—we’re tackling the six most common JavaScript errors head-on. We’ll break down what causes them, how to spot them, and most importantly, how to fix them.

By the end, you will know how to turn these coding speed bumps into stepping stones to better development practices.

The 6 JavaScript errors we will cover in this article include:

  1. SyntaxError
  2. ReferenceError
  3. TypeError
  4. RangeError
  5. URIError
  6. InternalError

1. SyntaxError - the grammar of code

SyntaxErrors are the most basic yet deceptive errors in JavaScript. They occur when your code violates the language’s syntax rules, breaking your script’s grammar.

Consider this example:

function calculateDiscount(price, percentage {
  return price * (1 - percentage);
}

At first glance, this function might seem correct. However, it’s missing a crucial closing parenthesis after percentage. This small oversight is enough to break the entire function.

How to fix a SyntaxError:

  1. Use an IDE or code editor with real-time syntax highlighting and error detection.
  2. Integrate ESLint into your workflow to catch syntax issues early.
  3. Pay close attention to matching pairs: parentheses, brackets, and curly braces.

Correct version:

function calculateDiscount(price, percentage) {
  return price * (1 - percentage);
}

Pro tip: Configure your editor to insert closing brackets and parentheses automatically. This feature can significantly reduce syntax errors, especially in complex nested structures.

Framework considerations:

  • React: If not correctly formatted, JSX syntax in React components can be prone to SyntaxErrors. The React Dev Tools extension for browsers can help identify these issues.
  • Vue: The Vue CLI provides built-in linting, which can catch many syntax errors before they reach the browser.
  • Angular: The Angular CLI includes a linting process that can identify many syntax issues during development.

2. ReferenceError - the undefined variable dilemma

ReferenceErrors occur when you try to use a variable that hasn’t been declared in the current scope. It’s like trying to spend money from an account you have yet to open.

Here’s a common scenario:

function updateUserProfile(user) {
  user.name = "Alice";
  console.log(userAge);
}
updateUserProfile({});

In this function, we’re trying to log userAge, which has yet to be declared anywhere. If we don’t, we’ll throw a ReferenceError.

How to fix a ReferenceError:

  1. Always declare variables before using them.
  2. Use const for values that won’t change and let for those that will.
  3. Be mindful of variable scope, especially in complex functions or loops.

Improved version:

function updateUserProfile(user) {
  user.name = "Alice";
  const userAge = 30; // Declare and initialize the variable
  console.log(userAge);
}
updateUserProfile({});

Pro tip: Enable strict mode ('use strict';) at the top of your JavaScript files or functions. This helps catch undeclared variables and other potential issues.

Framework considerations:

  • React: Misusing hooks like useState in React can lead to ReferenceErrors. Always call hooks at the top level of your functional components.
  • Vue: The Vue 3 Composition API requires careful management of reactive references, which, if mishandled, can lead to ReferenceErrors.
  • Angular: TypeScript, commonly used with Angular, helps prevent many ReferenceErrors through its static typing system.

3. TypeError - when data types clash

TypeErrors occur when you perform an operation on a value of an inappropriate type. It’s like trying to multiply a number by a string—it just doesn’t compute.

Let’s look at a typical scenario:

const user = {
  name: "Bob",
  greet: "Hello!"
};

user.greet();

This code throws a TypeError because we’re trying to call greet as a function, but it’s a string.

How to fix a TypeError:

  1. Always check the type of your variables before performing operations on them.
  2. Use type-checking functions like typeof or instanceof when necessary.
  3. Properly define object methods as functions.

Correct version:

const user = {
  name: "Bob",
  greet: function() {
    return "Hello!";
  }
};

console.log(user.greet()); // Outputs: Hello!

Pro tip: Consider using TypeScript for large projects. It adds static typing to JavaScript, catching many TypeErrors during development rather than at runtime.

Framework considerations:

  • React: Use PropTypes to catch TypeErrors related to component props, though TypeScript is increasingly popular.
  • Vue: Vue 3’s Composition API with TypeScript can help prevent many TypeErrors by providing better type inference.
  • Angular: Being built with TypeScript, Angular provides robust type checking out of the box, significantly reducing TypeErrors.

4. RangeError - stepping outside the boundaries

RangeErrors occur when you try to pass a value as an argument to a function that does not allow a range that includes the value. While less common, they can be tricky to debug.

A classic example is attempting to access an array element with an out-of-bounds index:

const scores = [85, 92, 78, 90];
console.log(scores[10]); // This doesn't throw a RangeError, it returns undefined
scores.pop(); // Remove the last element
console.log(scores.at(10)); // This throws a RangeError

This throws a RangeError because we’re trying to access an index outside the array’s bounds using the at() method.

How to fix a RangeError:

  1. Always validate array indices before accessing elements.
  2. Use conditional statements to check if values are within acceptable ranges before using them.
  3. Consider using methods like Array.prototype.at(), which provide more predictable behavior for out-of-bounds indices.

Safe array access:

function safeArrayAccess(arr, index) {
  if (index >= 0 && index < arr.length) {
    return arr[index];
  } else {
    console.error("Index out of bounds");
    return undefined;
  }
}

const scores = [85, 92, 78, 90];
console.log(safeArrayAccess(scores, 2)); // Outputs: 78
console.log(safeArrayAccess(scores, 10)); // Outputs: "Index out of bounds" and undefined

Pro tip: When working with user input or external data, always assume the data could be invalid and implement proper validation checks.

Framework considerations:

React, Vue, and Angular: These frameworks generally don’t have specific features for handling RangeErrors, as these are more related to core JavaScript operations. However, implementing proper data validation in your components can prevent many potential RangeErrors.

5. URIError: decoding the encoded

URIErrors are relatively rare but can occur when working with URIs (Uniform Resource Identifiers). They typically happen when using global URI handling functions with malformed parameters.

Here’s an example that would cause a URIError:

const badlyEncodedURI = "%E0%A4%A";
decodeURIComponent(badlyEncodedURI);

This code throws a URIError because %E0%A4%A is an incomplete UTF-8 encoding.

How to fix a URIError:

  1. Always properly encode URIs before attempting to decode them.
  2. Use try-catch blocks when working with URI encoding/decoding functions.

Safe URI decoding:

function safeDecodeURI(uri) {
  try {
    return decodeURIComponent(uri);
  } catch (e) {
    if (e instanceof URIError) {
      console.error("Malformed URI:", uri);
      return uri; // Return original string if decoding fails
    }
    throw e; // Re-throw if it's a different error
  }
}

const badlyEncodedURI = "%E0%A4%A";
console.log(safeDecodeURI(badlyEncodedURI)); // Outputs: %E0%A4%A

Pro tip: When working with URLs in a web application, consider using the URL and URLSearchParams APIs for safer and more convenient URL manipulation.

Framework considerations:

React Router, Vue Router, and Angular Router: These routing libraries handle much of the URL parsing and manipulation, which can help prevent URIErrors. However, it’s still important to handle encoding and decoding carefully when working with query parameters or hash fragments.

6. InternalError: the recursion rabbit hole (Stack Overflow)

InternalErrors are rare in modern JavaScript environments but can occur in cases of extreme recursion or when the JavaScript engine runs out of memory. This type of error is often referred to as a “Stack Overflow” error, a term widely recognized in the programming community.

Consider this recursive function:

function countDown(n) {
  console.log(n);
  countDown(n - 1);
}
countDown(5);

While this might not throw an InternalError in all environments, it will cause a stack overflow due to infinite recursion.

How to fix an InternalError:

  1. Always include a base case in recursive functions to ensure termination.
  2. Consider using iteration instead of recursion for performance-critical code.
  3. Be mindful of memory usage, especially when working with large data structures.

Correct recursive function:

function countDown(n) {
  if (n < 0) return; // Base case
  console.log(n);
  countDown(n - 1);
}
countDown(5);

Pro Tip: Consider techniques like memoization or tail call optimization for complex recursive algorithms to improve performance and prevent stack overflow errors.

Framework considerations:

React, Vue, and Angular: While these frameworks don’t directly deal with recursion issues, they can indirectly lead to stack overflow errors if components are nested too deeply or if reactive computations create circular dependencies. It’s essential to design component hierarchies and state management carefully to avoid these issues.

Embracing errors as learning opportunities

Understanding these common JavaScript errors is more than just troubleshooting – it’s about writing cleaner, more robust code from the start. As you encounter these errors in your projects, remember that each one is an opportunity to refine your skills and deepen your understanding of JavaScript.

Here are some final tips to keep in mind:

  1. Read error messages carefully. They often contain valuable information about what went wrong and where.
  2. Use browser developer tools. The console and debugger are invaluable for tracking down errors.
  3. Write testable code. Unit tests can catch many errors before they make it to production.
  4. Keep learning. JavaScript and its ecosystem are constantly evolving. Stay updated with the latest best practices and features.

Remember, even experienced developers encounter errors. The difference lies in how quickly and efficiently they can diagnose and resolve them. With practice and patience, you’ll find yourself fixing errors and preventing them altogether.

Happy coding, and may your debugging sessions be short and insightful!

Not a Raygun customer yet? Try out the full Crash Reporting application free for 14 days! No credit card required.

If you enjoyed this article, you might also like: