Common JavaScript Errors and How to Fix Them

Avatar

By squashlabs, Last Updated: July 14, 2023

Common JavaScript Errors and How to Fix Them

More Articles from the Javascript series:

Common Syntax Errors

Syntax errors are one of the most common types of errors you may encounter when writing JavaScript code. These errors occur when the code violates the rules of the JavaScript language syntax. Fortunately, syntax errors are relatively easy to fix once you identify them.

Here are some common syntax errors and how to fix them:

1. Missing parentheses: Forgetting to include parentheses can cause syntax errors. For example, if you’re calling a function, make sure to include the parentheses after the function name. Here’s an example:

// Incorrect
console.log("Hello, world");

// Correct
console.log("Hello, world");

2. Missing semicolon: JavaScript uses semicolons to separate statements. Forgetting to add a semicolon at the end of a line can lead to syntax errors. Here’s an example:

// Incorrect
let greeting = "Hello, world"

// Correct
let greeting = "Hello, world";

3. Unmatched braces: Braces {} are used to define blocks of code, such as function bodies or loops. Forgetting to close a brace or using the wrong number of opening and closing braces can result in syntax errors. Here’s an example:

// Incorrect
function sayHello() {
  console.log("Hello, world!");

// Correct
function sayHello() {
  console.log("Hello, world!");
}

4. Misspelled keywords: JavaScript has reserved keywords that cannot be used as variable names or function names. Misspelling a keyword can lead to syntax errors. Here’s an example:

// Incorrect
let fonction = "Hello, world!";

// Correct
let function = "Hello, world!";

5. Missing or extra quotes: Quotes are used to define strings in JavaScript. Forgetting to include quotes or using the wrong type of quotes can cause syntax errors. Here’s an example:

// Incorrect
let message = Hello, world!;

// Correct
let message = "Hello, world!";

Remember, syntax errors can be easily fixed by carefully reviewing your code and making sure it adheres to the rules of the JavaScript language. Using a code editor with syntax highlighting can also help you catch syntax errors early on.

By being aware of these common syntax errors and knowing how to fix them, you’ll be better equipped to write clean and error-free JavaScript code.

Undefined Variables and Functions

One of the most common errors in JavaScript is the use of undefined variables and functions. This error occurs when you try to access a variable or call a function that has not been declared or assigned a value.

Let’s start with undefined variables. In JavaScript, variables need to be declared before they can be used. If you try to access a variable that has not been declared, you will get an “ReferenceError: [variable] is not defined” error. For example:

console.log(myVariable); // ReferenceError: myVariable is not defined

To fix this error, you need to make sure that the variable is declared before using it. You can declare variables using the var, let, or const keywords. For example:

var myVariable;
console.log(myVariable); // undefined

In this case, myVariable is declared but has not been assigned a value, so it has the value undefined. You can assign a value to the variable later in your code:

myVariable = 10;
console.log(myVariable); // 10

Now let’s move on to undefined functions. Similar to variables, functions need to be declared before they can be called. If you try to call a function that has not been declared, you will get a “TypeError: [function] is not a function” error. For example:

myFunction(); // TypeError: myFunction is not a function

To fix this error, you need to make sure that the function is declared before calling it. You can declare functions using the function keyword or using arrow function syntax (() => {}). For example:

function myFunction() {
  console.log("Hello!");
}

myFunction(); // Hello!

If you are using arrow function syntax, you need to assign the function to a variable before calling it:

const myFunction = () => {
  console.log("Hello!");
}

myFunction(); // Hello!

In summary, to avoid undefined variables and functions errors, always make sure to declare and assign values to variables before using them, and declare functions before calling them.

Null and Type Errors

One of the most common errors in JavaScript is the null error. This error occurs when you try to access a property or call a method on a variable that is null or undefined. For example:

var name = null;
console.log(name.length); // Uncaught TypeError: Cannot read property 'length' of null

In this code snippet, we are trying to access the length property of the name variable, which is set to null. However, since null does not have a length property, a TypeError is thrown.

To fix this error, you need to ensure that the variable is not null or undefined before accessing its properties or calling its methods. You can do this by using an if statement or the nullish coalescing operator (??).

Using an if statement:

var name = null;
if (name !== null) {
  console.log(name.length);
}

Using the nullish coalescing operator:

var name = null;
console.log(name ?? 'Unknown');

Type errors are another common type of error in JavaScript. These errors occur when you try to perform an operation on a value of the wrong type. For example:

var num = 42;
console.log(num.toUpperCase()); // Uncaught TypeError: num.toUpperCase is not a function

In this code snippet, we are trying to call the toUpperCase() method on a number, which is not a valid operation. A TypeError is thrown in this case.

To fix this error, you need to ensure that you are using the correct data type for the operation you want to perform. In the example above, you can convert the number to a string before calling the toUpperCase() method:

var num = 42;
console.log(num.toString().toUpperCase()); // "42"

By converting the number to a string using the toString() method, we can then call the toUpperCase() method on the resulting string.

Remember to always check for null or undefined values before accessing properties or calling methods, and ensure that you are using the correct data type for the operations you want to perform to avoid null and type errors in your JavaScript code.

Scope Issues

Scope is an important concept in JavaScript that determines the accessibility or visibility of variables, functions, and objects in some particular part of your code. Having a good understanding of scope is crucial to avoid common JavaScript errors. In this chapter, we will explore some scope issues that developers often encounter and learn how to fix them.

1. Global Scope Pollution

Global scope pollution occurs when variables or functions are declared without the proper use of the var, let, or const keywords, making them global variables or functions. This can lead to unexpected behavior and conflicts with other parts of your code. To fix this, always declare variables and functions with the appropriate keywords and limit their scope to where they are needed.

// Bad example - polluting the global scope
myVariable = 10;

// Good example - declaring a variable with appropriate scope
var myVariable = 10;

2. Function Scope Issues

JavaScript has function scope, which means that variables declared inside a function are only accessible within that function. If you try to access a function-scoped variable outside its function, you’ll encounter a scope issue. To resolve this, you can declare the variable outside the function or use the return statement to pass the value from the function to the outer scope.

function myFunction() {
  var myVariable = 10;
  console.log(myVariable);
}

myFunction(); // Output: 10
console.log(myVariable); // Error: myVariable is not defined

3. Block Scope Issues

Before the introduction of let and const in ES6, JavaScript had only function scope. Variables declared with var are function-scoped, which means they are accessible throughout the entire function, even if they are declared within a block statement like if, for, or while. This can lead to unintended consequences. To avoid block scope issues, use let or const instead of var.

if (true) {
  var myVariable = 10;
}

console.log(myVariable); // Output: 10

// Fix using let
if (true) {
  let myVariable = 10;
}

console.log(myVariable); // Error: myVariable is not defined

4. Lexical Scope Issues

Lexical scope, also known as static scope, refers to how scopes are determined in nested functions. In JavaScript, each function creates a new scope, and it has access to variables defined in its outer scope. However, variables defined in inner scopes are not accessible in outer scopes. It’s important to understand the lexical scope to avoid errors.

function outerFunction() {
  var outerVariable = 'I am outer';

  function innerFunction() {
    var innerVariable = 'I am inner';
    console.log(innerVariable);
    console.log(outerVariable);
  }

  innerFunction();
}

outerFunction();
// Output:
// I am inner
// I am outer

console.log(innerVariable); // Error: innerVariable is not defined
console.log(outerVariable); // Error: outerVariable is not defined

Understanding and fixing scope issues is crucial for writing reliable and maintainable JavaScript code. By being mindful of scope and properly managing variable visibility, you can avoid many common JavaScript errors.

Asynchronous Errors

JavaScript supports asynchronous programming, allowing you to execute code without blocking the execution of other code. This can greatly improve the performance of your applications, but it also introduces the possibility of encountering asynchronous errors.

Asynchronous errors occur when there is an issue with code that is being executed asynchronously, such as a callback function or a promise. These errors can be challenging to debug because they may not result in immediate failures or clear error messages.

One common type of asynchronous error is the “callback hell” or “pyramid of doom.” This occurs when you have multiple nested callback functions, making the code difficult to read and maintain. Here’s an example:

asyncFunction1(function (error, result1) {
  if (error) {
    console.error('Error:', error);
    return;
  }

  asyncFunction2(result1, function (error, result2) {
    if (error) {
      console.error('Error:', error);
      return;
    }

    asyncFunction3(result2, function (error, result3) {
      if (error) {
        console.error('Error:', error);
        return;
      }

      // Continue with the code...
    });
  });
});

To fix this issue, you can use Promises or async/await syntax. Promises allow you to chain asynchronous operations together, making the code more readable and avoiding the pyramid of doom. Here’s an example using Promises:

asyncFunction1()
  .then(function (result1) {
    return asyncFunction2(result1);
  })
  .then(function (result2) {
    return asyncFunction3(result2);
  })
  .then(function (result3) {
    // Continue with the code...
  })
  .catch(function (error) {
    console.error('Error:', error);
  });

Alternatively, you can use async/await syntax, which allows you to write asynchronous code that looks like synchronous code. Here’s an example using async/await:

async function doAsyncOperations() {
  try {
    const result1 = await asyncFunction1();
    const result2 = await asyncFunction2(result1);
    const result3 = await asyncFunction3(result2);

    // Continue with the code...
  } catch (error) {
    console.error('Error:', error);
  }
}

doAsyncOperations();

Another common asynchronous error is “race conditions,” where the outcome of a program depends on the timing of events. For example, if you have multiple asynchronous operations that update a shared resource, the order of execution can affect the final result. To fix race conditions, you can use techniques like locking mechanisms, atomic operations, or synchronization primitives.

Asynchronous errors can also occur due to incorrect error handling. For example, if you forget to handle errors in a promise chain or callback function, the error may go unnoticed, leading to unexpected behavior. Always make sure to handle errors appropriately to prevent silent failures in your code.

Asynchronous errors can be challenging to debug, but understanding common patterns and using best practices can help you avoid and fix them. By using techniques like Promises and async/await, you can write more readable and maintainable asynchronous code. Additionally, being mindful of race conditions and properly handling errors will contribute to more robust and reliable applications.

Handling Errors with Try…Catch

Errors are an inevitable part of programming, and JavaScript is no exception. However, JavaScript provides us with a powerful mechanism called try...catch to handle and gracefully recover from these errors.

The try...catch statement allows you to define a block of code that may throw an error, and provides a way to catch and handle that error if it occurs. This can be extremely useful in scenarios where you want to prevent your program from crashing due to an unexpected error.

The basic syntax of a try...catch statement is as follows:

try {
// code that may throw an error
} catch (error) {
// code to handle the error
}

In the try block, you place the code that you suspect may throw an error. If an error occurs within this block, JavaScript will immediately jump to the catch block.

The catch block takes a parameter (commonly named error or err) that represents the error object thrown by the try block. Inside the catch block, you can write code to handle the error in any way you see fit.

Here’s an example that demonstrates the basic usage of the try...catch statement:

try {
    // code that may throw an error
    const result = someUndefinedVariable * 2;
    console.log(result);
} catch (error) {
    // code to handle the error
    console.log("An error occurred: " + error.message);
}

In this example, we attempt to multiply an undefined variable someUndefinedVariable by 2. Since the variable is undefined, this code will throw a ReferenceError. However, instead of crashing the program, the error is caught by the catch block, which logs an error message to the console.

It’s important to note that the try...catch statement only catches errors that occur within its immediate block. If an error occurs in a function called within the try block, the catch block will not be triggered. To catch errors within function calls, you can place additional try...catch statements within those functions.

You can also use multiple catch blocks to handle different types of errors. This allows you to have fine-grained control over how different types of errors are handled. Here’s an example:

try {
    // code that may throw an error
    someUndefinedFunction();
} catch (error) {
    if (error instanceof ReferenceError) {
        console.log("ReferenceError occurred: " + error.message);
    } else if (error instanceof TypeError) {
        console.log("TypeError occurred: " + error.message);
    } else {
        console.log("An unknown error occurred: " + error.message);
    }
}

In this example, we call a function someUndefinedFunction that does not exist. The catch block checks the type of error using the instanceof operator and logs an appropriate error message based on the error type.

By using the try...catch statement effectively, you can ensure that your JavaScript code gracefully handles errors and provides a better user experience. It allows you to catch and handle errors in a controlled manner, preventing your program from crashing and allowing you to take appropriate action based on the error type.

Debugging Techniques

Debugging is an essential skill for any JavaScript developer. It involves finding and fixing errors or bugs in your code. Even experienced developers encounter errors from time to time, so it’s important to know how to effectively debug your code. In this section, we’ll explore some common debugging techniques and tools that can help you identify and resolve JavaScript errors.

1. Using console.log()

The simplest and most common debugging technique is to use the console.log() function. This function allows you to print values or messages to the browser console, which is a built-in developer tool available in most modern browsers.

Here’s an example of how to use console.log() to debug a piece of code:

function addNumbers(a, b) {
  console.log('Adding numbers:', a, b);
  return a + b;
}

console.log(addNumbers(5, 10));

When you run this code, you’ll see the following output in the console:

Adding numbers: 5 10
15

Using console.log() can help you understand the flow of your code, track the values of variables, and identify any unexpected behavior.

2. Debugging with breakpoints

Another powerful technique for debugging JavaScript is setting breakpoints in your code. Breakpoints allow you to pause the execution of your code at a specific line, giving you the opportunity to inspect variables and step through the code line by line.

To set a breakpoint in your code, you can use the developer tools provided by your browser. Simply open the developer tools, navigate to the “Sources” or “Debugger” tab, and click on the line number where you want to set the breakpoint.

Once the breakpoint is set, the code execution will pause at that line when it’s reached. You can then examine the values of variables, step through the code, and even modify variables to test different scenarios.

3. Using the debugger statement

If you prefer not to use breakpoints or if the code is not executing within a browser context (e.g., in a Node.js environment), you can use the debugger statement to achieve a similar effect.

The debugger statement is a JavaScript keyword that causes the code execution to pause whenever it’s reached. You can place the debugger statement anywhere in your code to halt the execution and start debugging.

Here’s an example:

function divide(a, b) {
  debugger;
  return a / b;
}

console.log(divide(10, 2));

When you run this code in a browser console or with a debugger tool, it will pause at the debugger statement and allow you to inspect the state of your code.

4. Using try-catch blocks

JavaScript provides a try-catch statement that allows you to handle errors gracefully and provide fallback behavior when something goes wrong.

By wrapping a block of code in a try statement, you can catch any errors that occur within that block and handle them accordingly.

Here’s an example:

try {
  // Code that may throw an error
  const result = someUndefinedVariable + 10;
  console.log(result);
} catch (error) {
  // Code to handle the error
  console.log('An error occurred:', error);
}

In this example, if the variable someUndefinedVariable is not defined, an error will be thrown. However, because it’s wrapped in a try-catch block, the error will be caught and the catch block will be executed, which will log the error message to the console.

Using try-catch blocks can help you identify and handle errors without crashing your entire application.

5. Utilizing browser developer tools

Modern web browsers provide powerful developer tools that can assist you in debugging JavaScript code. These tools include features like real-time code inspection, network monitoring, profiling, and more.

To access the developer tools in most browsers, right-click on a web page and select “Inspect” or press the F12 key.

Some popular browser developer tools include:

– Chrome DevTools: https://developers.google.com/web/tools/chrome-devtools
– Firefox Developer Tools: https://developer.mozilla.org/en-US/docs/Tools
– Safari Web Inspector: https://developer.apple.com/safari/tools/

These tools offer a wide range of features to help you debug your code effectively and optimize the performance of your JavaScript applications.

Debugging JavaScript can be challenging, but with the right techniques and tools, you can quickly identify and fix errors in your code. Using console.log(), setting breakpoints, using the debugger statement, using try-catch blocks, and utilizing browser developer tools are all valuable techniques to have in your debugging toolbox.

Common Logic Errors

Logic errors are bugs in your code that cause it to behave unexpectedly or produce incorrect results. Unlike syntax errors, logic errors do not result in immediate error messages. Instead, they cause your program to produce incorrect results or behave in ways that you did not intend. These errors can be tricky to identify and fix, but with some debugging techniques, you can track them down and resolve them.

Here are some common logic errors in JavaScript and how to fix them:

1. Off-by-one Errors

Off-by-one errors occur when you mistakenly iterate over a collection or array with one too many or too few iterations. This can cause unexpected behavior, such as accessing elements that do not exist or skipping elements that should be processed.

Consider the following example:

for (let i = 0; i <= array.length; i++) {
  // Access elements of the array
}

In this code, the loop condition should be i < array.length instead of i <= array.length. The <= operator will cause the loop to iterate one extra time, leading to an out-of-bounds error when accessing the last element of the array.

To fix this error, simply change the loop condition to i < array.length.

2. Incorrect Comparisons

Logic errors can also occur when you use incorrect comparison operators. For example, using the assignment operator (=) instead of the equality operator (== or ===) can lead to unexpected results.

Consider the following example:

let x = 10;

if (x = 5) {
  console.log("x is equal to 5");
} else {
  console.log("x is not equal to 5");
}

In this code, the assignment operator = is used instead of the equality operator == or ===. As a result, the condition x = 5 will always evaluate to true, and the code will output “x is equal to 5” regardless of the actual value of x.

To fix this error, change the assignment operator to the equality operator:

if (x === 5) {
  console.log("x is equal to 5");
} else {
  console.log("x is not equal to 5");
}

3. Infinite Loops

Infinite loops occur when a loop condition never becomes false, causing the loop to run indefinitely. This can happen if you forget to update the loop variable or mistakenly use the wrong condition.

Consider the following example:

let i = 0;

while (i < 10) {
  // Do something
}

In this code, the loop condition i < 10 will always be true because the loop variable i is not updated inside the loop. As a result, the loop will continue to run indefinitely, causing your program to hang.

To fix this error, make sure to update the loop variable inside the loop:

let i = 0;

while (i < 10) {
  // Do something

  i++; // Update the loop variable
}

By updating the loop variable i inside the loop, the condition i < 10 will eventually become false, terminating the loop.

4. Incorrect Boolean Logic

Logic errors can also occur when you use incorrect boolean logic in your code. For example, using the wrong boolean operators (&&, ||, !) or incorrectly negating a condition (!) can lead to unexpected results.

Consider the following example:

let x = 5;
let y = 10;

if (x > 0 && y > 0 || x < 0 && y < 0) {
  console.log("x and y have the same sign");
} else {
  console.log("x and y have different signs");
}

In this code, the boolean logic is incorrect. The condition x > 0 && y > 0 || x < 0 && y < 0 will always evaluate to true because the && operator has higher precedence than the || operator. As a result, the code will output “x and y have the same sign” even if x and y have different signs.

To fix this error, use parentheses to group the conditions correctly:

if ((x > 0 && y > 0) || (x < 0 && y < 0)) {
  console.log("x and y have the same sign");
} else {
  console.log("x and y have different signs");
}

By using parentheses to group the conditions, you ensure that the correct boolean logic is applied, and the code will produce the expected results.

These are just a few examples of common logic errors in JavaScript. Remember to thoroughly test your code and use debugging techniques, such as console logging and stepping through your code, to identify and fix logic errors.

Working with Arrays

Arrays are a fundamental data structure in JavaScript that allow you to store and manipulate multiple values in a single variable. However, working with arrays can sometimes lead to errors if not done correctly. In this chapter, we will explore some common JavaScript errors that you may encounter when working with arrays and how to fix them.

1. Index Out of Range

One of the most common errors when working with arrays is accessing an element that does not exist. JavaScript arrays are zero-indexed, which means the first element is accessed using the index 0. If you try to access an element at an index that is out of range, you will get an “undefined” value.

let fruits = ['apple', 'banana', 'orange'];

console.log(fruits[3]); // undefined

To fix this error, make sure you are using a valid index within the range of the array’s length. You can use the array’s length property to check the number of elements in the array before accessing a specific index.

2. Incorrect Array Initialization

Another common error is incorrectly initializing an array. This can happen when you forget to use the square brackets [] or mistakenly use parentheses () instead.

// Incorrect initialization
let numbers = (1, 2, 3, 4, 5);

console.log(numbers); // 5

// Correct initialization
let numbers = [1, 2, 3, 4, 5];

console.log(numbers); // [1, 2, 3, 4, 5]

To fix this error, ensure that you are using square brackets to initialize the array and separate the elements using commas.

3. Array Methods and Mutability

JavaScript provides several built-in methods for working with arrays, such as push(), pop(), shift(), and unshift(). These methods allow you to add or remove elements from the beginning or end of an array. However, it’s important to note that some of these methods modify the original array, while others return a new array.

let numbers = [1, 2, 3];

numbers.push(4);
console.log(numbers); // [1, 2, 3, 4]

numbers.pop();
console.log(numbers); // [1, 2, 3]

let newNumbers = numbers.concat([4, 5]);
console.log(newNumbers); // [1, 2, 3, 4, 5]

console.log(numbers); // [1, 2, 3]

To avoid unexpected behavior, be aware of whether a method mutates the original array or returns a new array. If you need to create a new array, use methods like concat() or the spread operator ... to avoid modifying the original array.

4. Type Errors with Arrays

JavaScript is a dynamically typed language, which means you can add values of different types to an array. However, this can lead to type errors when performing operations on the array elements.

let mixedArray = ['apple', 3, true];

console.log(mixedArray[0].toUpperCase()); // 'APPLE'
console.log(mixedArray[1] + 2); // 5
console.log(mixedArray[2].length); // undefined

console.log(mixedArray); // ['apple', 3, true]

To fix type errors, make sure you are using the correct methods and operators for the specific data types you are working with. You can also use conditional statements or type checking to handle different types appropriately.

5. Iterating Over Arrays

When iterating over arrays, it’s important to use the correct looping construct or array method. Common errors include off-by-one errors, infinite loops, or not using the correct index variable.

let numbers = [1, 2, 3, 4, 5];

// Incorrect loop
for (let i = 0; i <= numbers.length; i++) {
  console.log(numbers[i]);
}

// Correct loop
for (let i = 0; i < numbers.length; i++) {
  console.log(numbers[i]);
}

// Using array method
numbers.forEach((number) => {
  console.log(number);
});

To iterate over an array correctly, use a loop that goes from 0 to the array’s length minus one or use array methods like forEach(). Ensure that you are using the correct index variable and conditions to avoid errors.

Working with arrays in JavaScript can be challenging, but understanding these common errors and how to fix them will help you write more reliable and bug-free code.

Manipulating Strings

Strings are a fundamental data type in JavaScript, and they are often manipulated to perform various operations. However, there are a few common errors that developers encounter when working with strings. In this chapter, we will explore these errors and provide solutions to fix them.

1. Concatenation Error

Concatenation is the process of combining two or more strings. One common error that occurs during concatenation is when a string is inadvertently treated as a number. This can happen if you forget to convert a number to a string before concatenating it.

To fix this error, you can use the toString() method to convert the number to a string before concatenating it. Here’s an example:

let num = 42;
let str = "The answer is " + num.toString();

2. String Length Error

The length property in JavaScript returns the number of characters in a string. However, when working with non-ASCII characters or multi-byte characters, the length property may not provide the expected result.

To accurately determine the length of a string that contains non-ASCII characters, you can use the charCodeAt() method in a loop. Here’s an example:

function getStringLength(str) {
  let length = 0;
  for (let i = 0; i < str.length; i++) {
    if (str.charCodeAt(i) > 255) {
      length += 2;
    } else {
      length++;
    }
  }
  return length;
}

3. Case Conversion Error

JavaScript provides methods to convert a string to uppercase or lowercase. However, these methods may not produce the expected result when working with non-ASCII characters.

To correctly convert the case of a string that contains non-ASCII characters, you can use the toLocaleUpperCase() and toLocaleLowerCase() methods. Here’s an example:

let str = "Äpfel";
let uppercase = str.toLocaleUpperCase();
let lowercase = str.toLocaleLowerCase();

4. Substring Error

The substring() method in JavaScript is used to extract a portion of a string. One common error occurs when specifying the start and end indices incorrectly.

To fix this error, pay attention to the indices you provide to the substring() method. The start index should be less than the end index. Here’s an example:

let str = "Hello, world!";
let substring = str.substring(7, 12); // "world"

By being aware of these common errors and their solutions, you can manipulate strings more effectively in your JavaScript code.

DOM Manipulation Errors

When working with JavaScript, one common task is manipulating the Document Object Model (DOM) to dynamically update the content of a webpage. However, there are several common errors that developers may encounter when performing DOM manipulation. In this chapter, we will explore some of these errors and provide solutions to fix them.

1. Undefined Element

One of the most common DOM manipulation errors is when attempting to access an element that does not exist in the DOM. This can happen when a typo is made in the element’s ID or class name, or when the element is not yet loaded when the JavaScript code is executed.

To fix this error, ensure that the element you are trying to access exists in the DOM and is loaded before accessing it. You can do this by wrapping your code in a DOMContentLoaded event listener, which ensures that the code is executed only when the DOM is fully loaded.

document.addEventListener("DOMContentLoaded", function() {
  // DOM manipulation code here
});

2. Incorrect Attribute or Property

Another common error is when trying to access or modify an incorrect attribute or property of a DOM element. This can happen when a typo is made in the attribute or property name, or when trying to access a property that does not exist for that particular element.

To fix this error, double-check the attribute or property name you are trying to access or modify. Make sure it is spelled correctly and exists for the selected element. You can refer to the documentation for the specific element you are working with to verify the correct attribute or property names.

var element = document.getElementById("myElement");
element.innerHTML = "New content";

3. Invalid CSS Selector

When using methods like querySelector or querySelectorAll to select elements in the DOM, it is common to encounter errors when using an invalid CSS selector. This can happen when the selector syntax is incorrect or when trying to select an element that does not exist.

To fix this error, review the CSS selector you are using and ensure it follows the correct syntax. You can test your selector using browser developer tools or online tools like W3Schools CSS Selector TryIt. Also, verify that the selected element(s) actually exist in the DOM.

var element = document.querySelector(".myClass");

4. Asynchronous Execution

DOM manipulation errors can also occur when trying to access or modify elements before they have been fully loaded or created. This is common when executing JavaScript code asynchronously, such as using the defer or async attributes on script tags.

To fix this error, ensure that your JavaScript code is executed after the elements you are trying to manipulate have been fully loaded or created. You can achieve this by placing your script tag at the end of the HTML document, just before the closing </body> tag, or by using the defer attribute on the script tag.

<script defer src="script.js"></script>

In this chapter, we have explored some common errors that developers may encounter when performing DOM manipulation in JavaScript. By understanding and addressing these errors, you can ensure that your code functions as intended and provides a smooth user experience.

Event Handling Errors

Event handling is a crucial aspect of JavaScript development, as it allows us to respond to user interactions and create dynamic web applications. However, there are common errors that can occur when working with event handling in JavaScript. In this chapter, we will explore some of these errors and learn how to fix them.

1. Syntax Errors

Syntax errors are one of the most common mistakes when it comes to event handling in JavaScript. These errors occur when we have a typo or an incorrect syntax in our code. Let’s take a look at an example:

document.getElementById('myButton').addEventListener('click', function() {
  // Code to execute when the button is clicked
});

In this code snippet, we are using the addEventListener method to attach a click event handler to a button with the id ‘myButton’. If we have a syntax error, such as a missing closing parenthesis or a misspelled method name, it will result in an error and prevent the event handler from being attached. To fix syntax errors, carefully review your code and ensure all parentheses, brackets, and method names are correctly written.

2. Context Errors

Another common error when handling events in JavaScript is related to the context of the event handler function. The context, represented by the this keyword, can be different depending on how the event handler is defined. Let’s consider the following example:

const myObject = {
  handleClick: function() {
    console.log(this); // Output: undefined
  }
};

document.getElementById('myButton').addEventListener('click', myObject.handleClick);

In this code snippet, we defined an object myObject with a method handleClick. We then try to attach this method as an event handler to a button. However, when the button is clicked, the context (represented by this) inside the handleClick function will be undefined. This happens because the context is determined at the moment the function is called, not when it is defined.

To fix context errors, we can use the bind method to explicitly set the context of the event handler function. Here’s an updated version of the code:

const myObject = {
  handleClick: function() {
    console.log(this); // Output: Object {handleClick: ƒ}
  }
};

document.getElementById('myButton').addEventListener('click', myObject.handleClick.bind(myObject));

By using the bind method, we ensure that the context of the handleClick function is always our myObject object, regardless of how it is called.

3. Event Propagation Errors

Event propagation refers to the way events are handled by nested elements in the DOM tree. Sometimes, when working with event handling, we may encounter errors related to event propagation. One common issue is when an event handler is triggered multiple times due to event propagation.

To prevent event propagation errors, we can use the stopPropagation method of the event object. This method stops the event from bubbling up the DOM tree, preventing any parent elements from triggering their event handlers. Here’s an example:

document.getElementById('innerDiv').addEventListener('click', function(event) {
  event.stopPropagation();
  console.log('Inner div clicked');
});

document.getElementById('outerDiv').addEventListener('click', function() {
  console.log('Outer div clicked');
});

In this code snippet, we have an inner div and an outer div. Both divs have their own click event handlers. Without the stopPropagation method, clicking on the inner div would trigger both event handlers, resulting in two console log statements. However, by calling event.stopPropagation(), we prevent the event from reaching the outer div’s event handler.

4. Asynchronous Errors

Asynchronous operations, such as AJAX requests or setTimeout, can also introduce errors when handling events in JavaScript. These errors occur when we expect certain operations to complete before executing event handlers.

To avoid asynchronous errors, we can use promises or async/await to ensure that our event handlers are executed only after the asynchronous operations have completed. Here’s an example using promises:

document.getElementById('myButton').addEventListener('click', function() {
  fetch('https://api.example.com/data')
    .then(function(response) {
      return response.json();
    })
    .then(function(data) {
      console.log(data);
    })
    .catch(function(error) {
      console.error(error);
    });
});

In this code snippet, when the button is clicked, we make an AJAX request to retrieve data from an API. By chaining promises, we ensure that the event handler code is executed only after the data has been successfully retrieved.

In this chapter, we explored common event handling errors in JavaScript and learned how to fix them. By paying attention to syntax, context, event propagation, and asynchronous operations, we can create robust and error-free event handling code.

Working with Forms

Forms are a fundamental part of web development, allowing users to input data and interact with a website. However, working with forms in JavaScript can sometimes lead to errors. In this chapter, we will explore some common JavaScript errors that you may encounter when working with forms, and how to fix them.

1. Accessing Form Elements

One common error when working with forms is accessing form elements. In JavaScript, you can access form elements using the querySelector method or by using the getElementById method. Here’s an example:

// Using querySelector
const myForm = document.querySelector('#myForm');
const usernameInput = myForm.querySelector('#username');

// Using getElementById
const myForm = document.getElementById('myForm');
const usernameInput = document.getElementById('username');

Make sure that you have the correct IDs for your form and form elements. If you receive an error stating that the element is null or undefined, double-check that the ID is correct.

2. Preventing Form Submission

Another common error is preventing form submission. Oftentimes, you may want to perform some validation before allowing the form to be submitted. To prevent the form from being submitted, you can use the preventDefault method. Here’s an example:

const myForm = document.getElementById('myForm');

myForm.addEventListener('submit', function(event) {
  event.preventDefault();

  // Perform validation
  // If validation passes, submit the form
});

By calling event.preventDefault(), you can stop the default behavior of the form submission and perform any necessary validation before submitting the form.

3. Handling Form Validation

Form validation is an important part of working with forms. JavaScript provides built-in form validation methods, such as checkValidity, which can be used to check if a form is valid. Here’s an example:

const myForm = document.getElementById('myForm');

myForm.addEventListener('submit', function(event) {
  event.preventDefault();

  if (myForm.checkValidity()) {
    // Form is valid, submit it
  } else {
    // Form is invalid, display error messages
  }
});

You can also manually validate form elements using the validity property and the setCustomValidity method. This allows you to display custom error messages to the user.

4. Handling Form Events

When working with forms, it’s important to handle form events properly. Common form events include submit, input, and change. Here’s an example:

const myForm = document.getElementById('myForm');

myForm.addEventListener('submit', function(event) {
  event.preventDefault();

  // Perform form submission
});

myForm.addEventListener('input', function(event) {
  // Handle input event
});

myForm.addEventListener('change', function(event) {
  // Handle change event
});

By handling these events, you can perform actions based on user input and respond to changes in form values.

Working with forms in JavaScript can be challenging at times, but with these common errors and their corresponding fixes in mind, you’ll be better equipped to handle them. Remember to always test your forms thoroughly to ensure they are functioning as expected.

AJAX Errors

AJAX (Asynchronous JavaScript and XML) is a powerful feature in JavaScript that allows you to send and receive data from a server asynchronously without interfering with the rest of the page. However, like any other technology, it is not immune to errors. In this chapter, we will explore some common AJAX errors and learn how to fix them.

1. Network Errors

Network errors are one of the most common types of errors when working with AJAX. These errors occur when there is an issue with the network connection, such as a server timeout, a DNS resolution problem, or a server that is down. To handle network errors, you can use the error event handler in your AJAX request. Here’s an example:

$.ajax({
  url: "https://api.example.com/data",
  success: function(response) {
    // Handle successful response
  },
  error: function(xhr, status, error) {
    console.log("An error occurred: " + error);
  }
});

In the example above, the error callback function is invoked when there is an error in the AJAX request. The xhr parameter contains the XMLHttpRequest object, the status parameter contains the status of the error, and the error parameter contains the error message.

2. Cross-Origin Errors

Cross-Origin Resource Sharing (CORS) is a mechanism that allows servers to specify who can access their resources. When making AJAX requests to a different domain, you may encounter cross-origin errors if the server does not allow your domain to access its resources.

To fix cross-origin errors, you can either configure the server to allow cross-origin requests or use a proxy server. If you have control over the server, you can add the appropriate headers to allow cross-origin requests. Otherwise, you can set up a proxy server that acts as an intermediary between your client and the server.

3. Syntax Errors

Syntax errors occur when the server returns a response with invalid JSON or XML syntax. This can happen if the server-side code generating the response is broken or if the response is not properly formatted. To handle syntax errors, you can use the dataType option in your AJAX request to specify the expected data type. For example:

$.ajax({
  url: "https://api.example.com/data",
  dataType: "json",
  success: function(response) {
    // Handle successful JSON response
  },
  error: function(xhr, status, error) {
    console.log("An error occurred: " + error);
  }
});

In the example above, the dataType option is set to “json” to indicate that the expected response is JSON. If the server returns a response with invalid JSON syntax, the error callback function will be invoked.

4. Server-side Errors

Server-side errors occur when there is an issue on the server-side code that handles the AJAX request. These errors can include database connection errors, SQL syntax errors, or any other server-side issues. To handle server-side errors, you can use the error event handler in your AJAX request, similar to handling network errors.

$.ajax({
  url: "https://api.example.com/data",
  success: function(response) {
    // Handle successful response
  },
  error: function(xhr, status, error) {
    console.log("An error occurred: " + error);
  }
});

In the example above, the error callback function is invoked when there is an error on the server-side code. The xhr parameter contains the XMLHttpRequest object, the status parameter contains the status of the error, and the error parameter contains the error message.

5. Handling Errors Globally

To handle AJAX errors globally, you can use the ajaxError event handler in jQuery. This event handler is triggered whenever an AJAX request encounters an error. Here’s an example:

$(document).ajaxError(function(event, xhr, settings, error) {
  console.log("An error occurred: " + error);
});

In the example above, the ajaxError event handler is attached to the document object. Whenever an AJAX request encounters an error, the callback function will be invoked, and the error message will be logged to the console.

By understanding and properly handling these common AJAX errors, you can ensure that your web applications provide a smooth and error-free user experience.

Working with JSON

JSON (JavaScript Object Notation) is a popular data format that is used for transmitting and storing data. It is widely used in web development as a way to exchange data between a client and a server. In JavaScript, JSON data is represented as a string and can be easily parsed into a JavaScript object using the JSON.parse() method.

Parsing JSON

To parse a JSON string into a JavaScript object, you can use the JSON.parse() method. This method takes a JSON string as its parameter and returns the corresponding JavaScript object.

const json = '{"name":"John", "age":30, "city":"New York"}';
const obj = JSON.parse(json);

console.log(obj.name); // Output: John
console.log(obj.age); // Output: 30
console.log(obj.city); // Output: New York

Stringifying JSON

Conversely, if you have a JavaScript object and want to convert it into a JSON string, you can use the JSON.stringify() method. This method takes a JavaScript object as its parameter and returns the corresponding JSON string.

const obj = { name: "John", age: 30, city: "New York" };
const json = JSON.stringify(obj);

console.log(json); // Output: {"name":"John","age":30,"city":"New York"}

Handling Errors

When working with JSON, there are a few common errors you may encounter. One common error is a syntax error in the JSON string. This can occur if the JSON string is not properly formatted. To handle this error, you can wrap the JSON.parse() method with a try-catch block and catch the SyntaxError exception.

const json = '{"name":"John", "age":30, "city":"New York"';
try {
  const obj = JSON.parse(json);
  console.log(obj);
} catch (error) {
  console.error("Error parsing JSON:", error);
}

Another error you may encounter is a TypeError when trying to access a property of a parsed JSON object. This can occur if the property does not exist in the object. To handle this error, you can use the optional chaining operator (?.) or check if the property exists before accessing it.

const json = '{"name":"John", "age":30, "city":"New York"}';
const obj = JSON.parse(json);

console.log(obj.name); // Output: John
console.log(obj.address?.street); // Output: undefined

if (obj.address) {
  console.log(obj.address.street); // Output: undefined
}

Summary

Working with JSON in JavaScript is a common task when building web applications. The JSON.parse() method allows you to parse a JSON string into a JavaScript object, while the JSON.stringify() method allows you to convert a JavaScript object into a JSON string. It’s important to handle errors that may occur when working with JSON, such as syntax errors or accessing non-existent properties. By understanding how to work with JSON in JavaScript, you’ll be able to effectively exchange and manipulate data in your web applications.

Handling Errors in Promises

Promises are a powerful feature in JavaScript that allow for asynchronous programming. They provide a way to handle the results of an asynchronous operation, whether it succeeds or fails. However, if not handled properly, promises can also introduce errors that can be difficult to debug. In this section, we will explore common errors that can occur when working with promises and how to fix them.

Unhandled Promise Rejection

One of the most common errors when working with promises is the unhandled promise rejection. This occurs when a promise is rejected, but no error handler is provided to handle the rejection. If this happens, the error gets thrown and can cause your application to crash.

To fix this error, always make sure to provide an error handler using the .catch() method at the end of your promise chain. This will catch any rejections that occur in the chain and allow you to handle the error gracefully.

fetch('https://api.example.com/data')
  .then(response => {
    // process response
  })
  .catch(error => {
    console.error('Error:', error);
  });

Returning Promises

Another common error is forgetting to return a promise from within a promise chain. This can lead to unexpected behavior and can cause your code to break.

To fix this error, make sure to return the promise from within each .then() block in your chain. This ensures that the next .then() block in the chain will receive the correct value.

fetch('https://api.example.com/data')
  .then(response => {
    // process response
    return response.json();
  })
  .then(data => {
    // use the processed data
  })
  .catch(error => {
    console.error('Error:', error);
  });

Forgetting to Call .catch()

When chaining promises, it’s important to remember to call .catch() at the end of the chain to handle any errors that occur.

To fix this error, always include a .catch() block at the end of your promise chain. This will ensure that any errors that occur in the chain are caught and handled properly.

fetch('https://api.example.com/data')
  .then(response => {
    // process response
  })
  .then(data => {
    // use the processed data
  })
  .catch(error => {
    console.error('Error:', error);
  });

Async/Await Error Handling

If you’re using async/await syntax with promises, it’s important to handle errors properly. If an error occurs within an async function, it will be automatically converted into a rejected promise.

To handle errors in async functions, use the try-catch block to catch any errors that occur within the function. This allows you to handle the error in a more synchronous manner.

async function getData() {
  try {
    const response = await fetch('https://api.example.com/data');
    // process response
  } catch (error) {
    console.error('Error:', error);
  }
}

getData();

By using the try-catch block, you can catch any errors that occur within the async function and handle them gracefully.

Handling errors in promises is crucial for writing robust and reliable JavaScript code. By following the best practices outlined in this section, you can avoid common errors and ensure that your promises are properly handled.

Using Error Handling Libraries

When developing JavaScript applications, it is crucial to handle errors effectively to provide a smooth user experience and maintain the stability of the application. While JavaScript provides built-in error handling mechanisms, using error handling libraries can greatly simplify the process and offer additional features.

Why Use Error Handling Libraries?

Error handling libraries can enhance the error handling capabilities of JavaScript by providing more advanced features such as error tracking, error reporting, and error analytics. These libraries often offer a centralized platform to monitor and manage errors, making it easier to identify and fix issues in your code.

Sentry

One popular error handling library is Sentry. Sentry is an open-source platform that helps developers track, prioritize, and resolve errors in real-time. It supports various programming languages, including JavaScript, and offers features like error aggregation, issue tracking, and detailed error reports.

To use Sentry in your JavaScript application, you need to sign up for an account on the Sentry website and create a new project. Once you have your project set up, you can install the Sentry SDK using a package manager like npm or yarn.

Here’s an example of how to configure and use Sentry in a Node.js application:

const Sentry = require('@sentry/node');

Sentry.init({
  dsn: 'YOUR_SENTRY_DSN',
});

// Example error handling
try {
  // Code that may throw an error
} catch (error) {
  Sentry.captureException(error);
}

In the above example, we import the @sentry/node module and initialize it with our Sentry DSN (Data Source Name), which is provided by Sentry when you create a new project. We then wrap the code that may throw an error in a try-catch block and capture any caught errors using Sentry.captureException(error).

Rollbar

Another popular error handling library is Rollbar. Rollbar is a cloud-based platform that provides real-time error tracking and debugging tools. It supports JavaScript, among other languages, and offers features like error grouping, intelligent error filtering, and customizable error notifications.

To use Rollbar in your JavaScript application, you need to sign up for an account on the Rollbar website and create a new project. Once you have your project set up, you can install the Rollbar SDK using a package manager like npm or yarn.

Here’s an example of how to configure and use Rollbar in a browser-based JavaScript application:

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.rollbar.com/rollbar.min.js"></script>
  <script>
    Rollbar.init({
      accessToken: 'YOUR_ROLLBAR_ACCESS_TOKEN',
      captureUncaught: true,
      captureUnhandledRejections: true
    });

    // Example error handling
    try {
      // Code that may throw an error
    } catch (error) {
      Rollbar.error(error);
    }
  </script>
</head>
<body>
  <!-- Your application code -->
</body>
</html>

In the above example, we include the Rollbar JavaScript library in our HTML file using a script tag. We then initialize Rollbar with our Rollbar access token, which is provided by Rollbar when you create a new project. We enable capturing uncaught exceptions and unhandled promise rejections, and in the catch block, we log the error using Rollbar.error(error).

Optimizing Error Handling

Handling errors effectively is a crucial aspect of JavaScript development. It not only helps in identifying and resolving issues but also improves the overall quality and performance of your code. In this chapter, we will explore some strategies for optimizing error handling in JavaScript.

1. Use try-catch blocks

One of the fundamental ways to handle errors in JavaScript is by using try-catch blocks. This allows you to catch and handle exceptions that may occur during the execution of a specific code block. By wrapping potentially error-prone code within a try block, you can gracefully handle any errors that may arise.

Here’s an example of using a try-catch block:

try {
  // Code that may throw an error
} catch (error) {
  // Handle the error
}

Within the catch block, you can define the actions to be taken when an error occurs. This can include logging the error, displaying a user-friendly message, or taking any other appropriate steps to handle the error gracefully.

2. Avoid silent failures

Silent failures occur when errors are not properly handled or logged, making it difficult to identify and resolve issues. It is important to avoid silent failures as they can lead to unexpected behavior and make debugging a nightmare.

Instead of allowing errors to go unnoticed, make sure to log them or display meaningful error messages to users. This will help you quickly identify and fix any issues that may arise during application execution.

3. Use specific error handling

JavaScript provides various types of built-in error objects to handle specific types of errors. By using these specific error objects, you can catch and handle specific types of errors, rather than relying on generic catch blocks.

Here are some commonly used error objects:

Error: The base error object from which all other error objects inherit.
SyntaxError: Represents a syntax error in the code.
TypeError: Indicates that a value is not of the expected type.
ReferenceError: Indicates that an invalid reference is being accessed.

By using specific error objects, you can tailor your error handling logic to handle different types of errors in a more precise and targeted manner.

4. Implement error logging

Error logging is a crucial practice for identifying and diagnosing issues in your JavaScript code. By logging errors, you can gather valuable information about the errors that occur in your application, such as the stack trace, error message, and context in which the error occurred.

There are various ways to implement error logging, such as using the built-in console.error() method or integrating with third-party logging services. Choose a logging approach that best suits your application’s needs and ensure that error logs are easily accessible for analysis and debugging.

5. Gracefully handle asynchronous errors

When working with asynchronous code in JavaScript, errors can occur at various stages of execution, making them harder to handle. It is important to handle these asynchronous errors gracefully to prevent them from crashing your application.

To handle asynchronous errors, you can use the catch() method on Promises or try-catch blocks around asynchronous operations. This allows you to catch and handle any errors that occur during asynchronous execution.

Here’s an example of handling asynchronous errors with Promises:

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    // Handle the fetched data
  } catch (error) {
    // Handle any errors that occur during fetching or parsing
  }
}

By gracefully handling asynchronous errors, you can ensure that your application remains stable and responsive even when errors occur during asynchronous operations.

Optimizing error handling in JavaScript is vital for maintaining the quality and reliability of your code. By using try-catch blocks, avoiding silent failures, using specific error handling, implementing error logging, and gracefully handling asynchronous errors, you can enhance your error handling practices and effectively troubleshoot issues in your JavaScript applications.

Secure Error Handling

When it comes to error handling in JavaScript, it’s important to not only handle errors effectively but also to do so securely. Handling errors securely helps protect your application from potential security vulnerabilities and prevents sensitive information from being exposed to malicious users.

One common mistake is displaying detailed error messages to users without considering the potential risks. Detailed error messages can inadvertently expose sensitive information about your application, such as database connection details or API keys. Therefore, it’s crucial to ensure that error messages displayed to users are generic and don’t reveal any sensitive information.

Here’s an example of how to handle errors securely by displaying generic error messages:

try {
  // Code that may throw an error
} catch (error) {
  console.error("An error occurred. Please try again later.");
}

In this example, the catch block catches any error that occurs within the try block and logs a generic error message to the console. By avoiding detailed error messages, you prevent potentially sensitive information from being exposed to users.

Another important aspect of secure error handling is properly logging errors. Logging errors can help you identify and fix issues in your application, but it’s essential to handle them securely. Storing error logs in a secure location and restricting access to them is crucial to prevent unauthorized access to sensitive information.

Additionally, when logging errors, it’s a good practice to log only the necessary information and avoid logging sensitive data. For example, you might want to log the type of error, the stack trace, and any relevant contextual information, but avoid logging user input or any other sensitive data.

Here’s an example of how to log errors securely using the console.error method:

try {
  // Code that may throw an error
} catch (error) {
  console.error("An error occurred:", error);
  console.error("Stack trace:", error.stack);
}

In this example, the error message and stack trace are logged to the console, providing useful information for debugging purposes, but without revealing any sensitive data.

Secure error handling in JavaScript is essential for protecting your application from potential security vulnerabilities and preventing the exposure of sensitive information. By displaying generic error messages and properly logging errors, you can ensure that your application remains secure and users’ data is protected.

Error Logging and Monitoring

When working with JavaScript, it’s important to have a system in place for monitoring and logging errors. This will help you identify and fix issues in your code, leading to more robust and stable applications. In this chapter, we will explore some techniques for error logging and monitoring in JavaScript.

Console Logging

One of the simplest ways to log errors in JavaScript is by using the console. The console provides a set of logging methods that allow you to output messages to the browser’s console. You can use the console.log() method to log general information, including error messages and variable values.

console.log("Error: Something went wrong");

You can also use other methods provided by the console, such as console.error() to log specific error messages, and console.warn() to log warning messages.

Try…Catch Statements

Another powerful technique for error handling in JavaScript is using try…catch statements. This allows you to catch and handle errors in a controlled manner. The try block contains the code that may throw an error, and the catch block is used to handle the error if it occurs.

try {
  // Code that may throw an error
  throw new Error("Something went wrong");
} catch (error) {
  // Handle the error
  console.error(error);
}

By using try…catch statements, you can prevent your application from crashing when an error occurs and instead handle the error gracefully.

Error Objects

JavaScript provides an Error object that can be used to create custom error messages. The Error object has a message property that can be used to store the error message, and it also captures a stack trace, providing valuable information about where the error occurred.

try {
  throw new Error("Custom error message");
} catch (error) {
  console.error(error.message);
  console.error(error.stack);
}

By logging the error message and stack trace, you can gain insights into the cause of the error and easily debug your code.

Error Tracking Tools

In addition to console logging and try…catch statements, there are several error tracking tools available that can help you monitor and analyze errors in your JavaScript code. These tools provide detailed insights into the errors occurring in your application, including the frequency, the affected users, and the environment in which they occurred.

Some popular error tracking tools include:

Sentry
Bugsnag
Rollbar

These tools integrate with your codebase and provide real-time error monitoring, alerting, and analytics, making it easier to identify and fix errors in your JavaScript applications.

More Articles from the Javascript series:

Subscribe to our Newsletter

A curated list of the top stories in programming and DevOps.
Delivered weekly by a seasoned CTO.

We will never spam you. One email per week with latest updates.