17 common Node.js errors and how to solve them
Tags: node, webdev
Published: 2023-11-01 14:30:55

**Written by [David Omotayo](https://blog.logrocket.com/author/davidomotayo/)✏️**

Errors can be a significant challenge for developers, often leading to unnecessary time consumption. We might be quick to point fingers at the programming language or environment, but it is fair to acknowledge that many of these errors stem from developer mistakes and how we use these tools. 

Node.js has been around for quite some time and has been instrumental in building robust and sophisticated web services that have scaled effectively and stood the test of time. But, like every other runtime environment or platform, Node.js is susceptible to developer mistakes. 

In this article, we'll take a look at some of the most common Node.js errors you may encounter and we’ll discuss how to fix them. 

_Jump ahead:_

*   [Unhandled exceptions in streams](#unhandled-exceptions-streams)
    *   [Attach error event handlers](#attached-error-event-handlers)
    *   [Use try-catch with synchronous code](#use-try-catch-synchronous-code)
    *   [Use the pipeline method](#use-pipeline-method)
    *   [Use the `finished()` function](#use-finished-function)
*   [`JavaScript heap out of memory` error](#javascript-heap-out-of-memory)
    *   [Unclosed connections](#unclosed-connections)
    *   [Undisposed objects](#undisposed-objects)
    *   [Circular references](#circular-references)
    *   [Large applications](#large-applications)
*   [Environment compatibility errors](#environment-compatibility-errors)
    *   [`ReferenceError: document is not defined`](#referenceerror-document-is-not-defined)
    *   [`ReferenceError: window is not defined`](#referenceerror-window-is-not-defined)
    *   [`ReferenceError: XMLHttp Request is not defined`](#referenceerror-xmlhttp-request-is-not-defined)
*   [Network and communication errors](#network-communication-errors)
    *   [`Error: read ECONNRESET`](#error-read-econnreset)
    *   [`Error: connect ECONNREFUSED`](#error-connect-econnrefused)
    *   [`Error: listen EADDRINUSE: address already in use`](#error-listen-eaddrinuse-address-already-in-use)
    *   [`Error: write EPIPE`](#error-write-epipe)
*   [Additional common Node.js errors](#additional-common-node-js-errors)
    *   [`.find is not a function`](#find-is-not-a-function)
    *   [`Uncaught SyntaxError: Unexpected identifier`](#uncaught-syntaxerror-unexpected-identifier)

## Unhandled exceptions in streams <a name="unhandled-exceptions-streams">

Streams are a fundamental concept in Node.js for reading and writing to asynchronous data sources such as files, sockets, or HTTP requests. Errors can occur at any time during a stream's lifecycle. 

Streams emit errors during various operations, such as reading, writing, piping, or transforming data. The errors are emitted through the stream’s `error` event. If you do not attach an error handler to the stream, the errors will propagate up the event loop and potentially crash your application. 

Here’s an example of an unhandled exception in streams:

```javascript
const fs = require("fs");
const readStream = fs.createReadStream("nonexistent-file.txt");
// Without an error handler, this error will crash the application.
readStream.pipe(process.stdout);
```

Without an error handler, if the connection from the client is terminated abruptly, the `readStream` may not be closed when the error occurs. Instead, it will remain open indefinitely, leading to memory leaks in your application. 

This will likely result in unexpected behaviors and may lead to errors such as `unhandled stream error in pipe`, as shown below:

    stream.js:60
          throw er; // Unhandled stream error in pipe.
          ^
    Error: socket hang up
        at createHangUpError (_http_client.js:200:15)
        at Socket.socketOnEnd (_http_client.js:285:23)
        at emitNone (events.js:72:20)
        at Socket.emit (events.js:166:7)
        at endReadableNT (_stream_readable.js:905:12)
        at nextTickCallbackWith2Args (node.js:437:9)
        at process._tickCallback (node.js:351:17)

To address unhandled exception errors in Node.js streams you can use one of several solutions. Let’s take a look.

### Attach error event handlers <a name="attached-error-event-handlers">

Always attach an error event handler to catch and handle errors that occur during stream operations. This ensures that errors are caught and properly managed, preventing your app from crashing:

```javascript
const fs = require('fs');
const readStream = fs.createReadStream('example-file.txt');
readStream.on('error', (err) => {
  console.error('An error occurred:', err.message);
});
readStream.pipe(process.stdout);
```

### Use `try-catch` with synchronous code <a name="use-try-catch-synchronous-code">

When working with synchronous code that interacts with streams, you can wrap the code in a [`try-catch`](https://blog.logrocket.com/error-handling-node-js/#trycatch-blocks) to handle errors effectively. This will ensure that the program does not crash if an error occurs and that the error is handled in a controlled manner:

```javascript
const fs = require('fs');

try {
  const readStream = fs.createReadStream('example-file.txt', 'utf8');
  const dataPromise = new Promise((resolve, reject) => {
    let data = '';
    readStream.on('data', (chunk) => {
      data += chunk;
    });
    // Handle errors from the stream
    readStream.on('error', (err) => {
      reject(err); // Reject the promise if an error occurs
    });
    // When the stream ends, resolve the promise with the data
    readStream.on('end', () => {
      resolve(data);
    });
  });
  const fileData = await dataPromise;
  console.log('File contents:', fileData);
} catch (err) {
  console.error('An error occurred:', err.message); // Log error to the console
}
```

In the code above, we created a `try-catch` block that encapsulates a promise that is resolved when the stream ends successfully or is rejected if an error occurs. The error is then caught in the `catch` block, where it is logged.

### Use the pipeline method <a name="use-pipeline-method">

The previous options handle errors efficiently, but it can be unmanageable to attach event handlers to every stream when using the `pipe` method. Instead, the [`pipeline` method](https://blog.logrocket.com/working-node-js-streams/#node-streams-error-handling) offers a much cleaner and more manageable way to handle errors. 

A `pipeline` is a stream method that takes three arguments: a readable stream (the source of the stream), a writable stream (the destination of the stream), and a callback function that will be called if an error occurs during the process:

```javascript
const fs = require('fs');
const { pipeline } = require('stream');
const readStream = fs.createReadStream("inputexample.txt");
const writeStream = fs.createWriteStream("outputexample.txt");
pipeline(
  readStream, // Readable stream
  writeStream, // Writable stream
  (err) => {
    // Callback function to handle errors
    if (err) {
      console.error("Pipeline failed:", err);
    } else {
      console.log("Pipeline succeeded");
    }
  }
);
```

The `pipeline` method is particularly useful for file input/output and network operations, as it provides a cleaner and more robust way to transfer data from a readable stream to a writable stream while efficiently handling errors.

### Use the `finished()` function <a name="use-finished-function">

The `finished()` function is a stream method that handles cleanup and completion logic for streams. It is triggered when a stream is no longer readable or writable, or when it has experienced an error due to premature termination, such as an aborted HTTP request. 

The function emits an `end` or `finish` event when a stream has successfully ended. However, the function ignores these events and instead invokes a callback function, which it takes as a second argument to handle unexpected errors and prevent the application from crashing:

```javascript
const { finished } = require('node:stream');
const fs = require('node:fs');
const readStream = fs.createReadStream('input.txt');

finished(readStream, (err) => {
  if (err) {
    console.error('Read stream encountered an error:', err);
  } else {
    console.log('Read stream has finished successfully.');
  }
});
```

## `JavaScript heap out of memory` error <a name="javascript-heap-out-of-memory">

The `JavaScript heap out of memory` error can be caused by a number of factors, but the most prevalent is memory leaks in your application. A memory leak occurs when an application allocates memory but does not release it when it is no longer needed. 

This can happen when an application creates objects that are never deleted, or when an application holds onto references to objects that are no longer being used. Over time, memory leaks can cause an application to run out of memory and crash:

    app/web.1 FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

This error is rather ambiguous, and newer developers are often unsure how to resolve such an error. Let’s take a look at some of the most common causes of memory leaks in Node.js.

### Unclosed connections

When a connection to a database or other resource is not closed properly, the connection will remain open and consume memory:

```javascript
// A route that simulates a long-running operation without closing the connection
app.get('/unclosed', (req, res) => {
  // In a real scenario, this could be a database query, a file read, etc.
  setTimeout(() => {
    // This response is never sent, leaving the connection open
    console.log('Request handled, but the response is never sent.');
  }, 5000);
});

const port = 3000;

app.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});
```

In this example, the server does not send a response to the client. This causes the connection to remain open, and over time, these open connections can consume memory and lead to performance issues. 

To avoid this, your server should send a response to the client, even if it is a simple response indicating that the request was received. The server should also close the connection after sending the response.

### Undisposed objects

When an object is no longer needed, it should be disposed of to free up the memory it is using. Failure to do so can lead to memory leaks:

```javascript
const mysql = require('mysql2');

const pool = mysql.createPool({
  host: 'localhost',
  user: 'username',
  password: 'password',
  database: 'mydb',
  connectionLimit: 10, // Limit the number of concurrent connections
});

// Simulate a query that doesn't release the connection
function querySim() {
  pool.query('SELECT 1 + 1 AS result', (error, results) => {
    if (error) {
      console.error('Error:', error);
    } else {
      console.log('Result:', results[0].result);
    }
  });
}

// Periodically simulate queries (e.g., every 1 second)
setInterval(querySim, 1000);
```

In this example, the `querySim` function will continuously create new database connections using the connection pool without releasing them, leading to a memory leak. 

To avoid memory leaks in production, always release resources when done with them. Use `pool.end()` for database connections to close the connection pool effectively.

### Circular references

When two objects refer to each other, they can create a [circular reference](https://blog.logrocket.com/understanding-memory-leaks-node-js-apps/#optimizing-against-memory-leaks). This can prevent either object from being garbage collected, which can lead to memory leaks:

```javascript
// Repeating the process periodically to simulate a memory leak in a 
//production environment
setInterval(() => {
  // Create new objects with circular references
  const newObj1 = {};
  const newObj2 = {};

  newObj1.child = newObj2;
  newObj2.parent = newObj1;

}, 1000);
```

The above example simulates a situation in which two objects, `obj1` and `obj2`, are created repeatedly. Each object has a property that points to the other object, creating a circular reference. This prevents garbage collection. 

If this process continues over time, it can lead to memory leaks, as the objects with circular references will not be garbage collected and will continue to consume memory. This can eventually lead to the `JavaScript heap out of memory` error. 

To prevent memory leaks, break circular references when objects are no longer needed. Set properties to `null`, or use other techniques that break the circular references when the objects are no longer in use. 

Here’s how we could use `null` to break the references in the previous example:

```javascript
let newObj1, newObj2;

function circularObjects() {
  // If objects were previously created, break their references
  if (newObj1) {
    newObj1.child = null;
  }
  if (newObj2) {
    newObj2.parent = null;
  }

  // Create new objects with circular references
  newObj1 = {};
  newObj2 = {};

  newObj1.child = newObj2;
  newObj2.parent = newObj1;
}
setInterval(circularObjects, 1000);
```

### Large applications

The `JavaScript heap out of memory` error can also occur when an application grows larger and uses more objects that take up all the available heap memory allocated by Node.js (1.5GB) by default. 

To address this error, you can increase the maximum heap memory using the following commands: 

Linux or macOS:

```bash
node --max-old-space-size=4096 server.js
```

Windows:

*   *   Open the Command shell, or PowerShell as an administrator
    *   Navigate to your Node.js application directory using `cd`
    *   Run the following command:

```bash
node --max-old-space-size=4096 server.js
```

This command will start your Node.js application with 4GB of memory limit. 

A reliable approach to avoid memory leaks in Node.js is to follow best coding practices and utilize tools like the [Node.js Inspector](https://nodejs.org/api/inspector.html) to monitor and manage memory usage effectively.

## Environment compatibility errors

Environment compatibility errors can arise when code written for a specific environment, such as a web browser, is ported to a different environment where the expected features or objects are not available or behave differently. Let’s take a look at a few common reference errors.

### `ReferenceError: document is not defined` <a name="referenceerror-document-is-not-defined">

The `ReferenceError: document is not defined` error is the most common environment compatibility error encountered by developers who are used to working in the web browser environment and are new to Node.js:

    ReferenceError: document is not defined
    at Object.<anonymous> (C:\Users\Desktop\main.js:9:18)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3

This error indicates that you are attempting to access the `document` global object, which is typically available in web browsers as part of the DOM. However, Node.js is a runtime environment and does not have a DOM by default. That’s why attempting to access `document` in a Node.js environment will lead to the `ReferenceError: document is not defined` error:

```javascript
// This code tries to access the `document` object, which is not available outside a web browser
const title = document.title;
console.log(`Document title: ${title}`); // ReferenceError: document is not defined
```

If your task requires a DOM, you can use a library that provides a DOM for Node.js, such as Cheerio or Puppeteer. Otherwise, you can fix this error by checking the environment using the `typeof` operator to determine the specific environment your code is in before accessing the `document` object:

```javascript
if (typeof document === "object") {
  // Your browser-specific code here
  document.querySelectorAll("p");
  document.getElementById("table");
  console.log("Running in a browser environment");
} else {
  // Your non-browser code here
  console.log("Running in a non-browser environment");
}
```

This code will check if the `window` object is available in the runtime environment. It will execute the code in the `if` block if it returns `true`; otherwise, it will execute the code in the `else` block.

### `ReferenceError: window is not defined` <a name="referenceerror-window-is-not-defined">

The `ReferenceError:` `window` `is not defined` error occurs when you try to access the `window` object, which is specific to web browsers and not available in a Node.js runtime environment. The `window` object is the global object in a web browser. It contains properties and methods that are used to interact with the browser and its window. 

In a Node.js runtime environment, the global object is called `global`, and it does not contain the `window` object. Therefore, if you try to access the `window` object in a Node.js runtime environment, you will get the `ReferenceError: window is not defined` error. 

Similar to the previous error, you can fix the `ReferenceError:` `window` `is not defined` error by using a conditional statement and the `typeof` operator to check if your code is in the appropriate environment before it is executed:

```javascript
function nodeTask() {
  console.log('Doing a Node-specific task');
}

function browserTask() {
  console.log('Doing a Browser-specific task');
}

// Environment-specific code execution
if (typeof window === 'undefined') {
  // Check if 'window' is undefined, which typically indicates a Node.js environment
  nodeTask(); // Execute Node-specific code
} else {
  // If 'window' is defined, assume it's a browser environment
  browserTask(); // Execute Browser-specific code
}
```

### `ReferenceError: XMLHttp Request is not defined` <a name="referenceerror-xmlhttp-request-is-not-defined">

The `ReferenceError: XMLHttpRequest is not defined` error occurs when you try to use the `XMLHttpRequest` constructor in Node.js to make HTTP requests, as shown in the following example:

```javascript
try {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', 'https://example.com', true);
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
      console.log(xhr.responseText);
    }
  };
  xhr.send();
} catch (error) {
  console.error('Error:', error);
}
```

The `XMLHttpRequest` method is a browser-specific API. However, unlike the `window` and `document`, it is not a global object, but a constructor for interacting with servers. Due to the agnostic nature of its operation, it is easy to make the mistake of using the `XMLHttpRequest` method in a non-browser environment like Node.js. 

To fix the `ReferenceError: XMLHttpRequest is not defined` error, use an alternative package such as `node-fetch` or `axios`, which are recent and provide more developer-friendly ways of interacting with the server. You can install these packages using the following commands:

```bash
npm install node-fetch
npm install axios
```

## Network and communication errors <a name="network-communication-errors">

Network and communication errors are a series of errors that typically occur during network communication between your Node.js application and other systems, such as databases, web servers, and other networked resources. These errors can be caused by various factors related to network connectivity, data transmission, and more. Let’s look at some common network and communication errors in Node.js and how to solve them.

### `Error: read ECONNRESET` <a name="error-read-econnreset">

The `Error: read ECONNRESET` error occurs when the connection to a remote server has unexpectedly closed, usually before the response is received, causing the HTTP request to fail:

    Error: read ECONNRESET
    at errnoException (server.js:900:11)
    at TCP.onread (server.js:555:19)

This can be caused by a number of factors, such as the remote server being overloaded, your Node.js application sending too much data, or the remote server experiencing a power outage. 

To resolve this error, do any of the following:

*   Reduce the amount of data that your Node.js application is sending
*   Try to connect to the remote server at a later time
*   Make sure your request configuration is correct. This includes the HTTP method (e.g., `GET` or `POST`), the host name (e.g., logrocket.com), the path (e.g., /blog), and more
*   Test your network connection
*   Increase connection timeout; the server may be timing out before a connection is established

### `Error: connect ECONNREFUSED` <a name="error-connect-econnrefused">

The `Error: connect ECONNREFUSED` error occurs when a connection from your Node.js application to a remote server cannot be established:

```javascript
Error: connect ECONNREFUSED
    at errnoException (net.js:770:11)
    at Object.afterConnect [as oncomplete] (net.js:761:19)
```

This error can be caused by a number of factors, such as the remote server being down, the Node.js application not being able to reach the remote server, the remote server refusing the connection, or sending requests to the wrong endpoint or port. 

To resolve this error, check the status of the remote server, verify that your Node.js application is running and is able to reach the remote server, and make sure that the remote server is not refusing the connection.

### `Error: listen EADDRINUSE: address already in use` <a name="error-listen-eaddrinuse-address-already-in-use">

`Error: listen EADDRINUSE: address already in use` is not so much a communication error, but an error that occurs when the port where you’re trying to start your Node.js application is already in use by another process:

    Error: listen EADDRINUSE: address already in use :::3000
    Emitted 'error' event on Server instance at:
        at emitErrorNT (node:net:1544:8)
        at process.processTicksAndRejections (node:internal/process/task_queues:84:21) {
      code: 'EADDRINUSE',
      errno: -98,
      syscall: 'listen',
      address: '::',
      port: 3000
    }

In the above example, the error message indicates that the port `3000` is already in use by another process. This means that the port is currently occupied and cannot be used for the current request. 

To resolve this error, you can either stop the process that is using the specified port or configure your applications to run on a different port. To do the former, execute the following command in your terminal:

```bash
npx kill-port 3000
```

Note that this command will kill the process immediately, without any chance to save any unsaved data. 

For macOS, use the following command to view information about the process that is using the port:

```bash
lsof -i :3000
```

You will receive a response that includes a process ID, `PID` ,number. Copy that number and run the following command with it:

```bash
kill -9 <PID number> 
```

This command will terminate the process, after which you can start your Node.js application without any errors.

### `Error: write EPIPE` <a name="error-write-epipe">

The `Error: write EPIPE` or “broken pipe” error occurs when your Node.js application tries to write data to a socket or a stream that has been closed or unexpectedly terminated at the other end of the connection. The error typically happens when your application continuously tries to write to the closed connection:

    Error: write EPIPE
        at errnoException (net.js:770:11)
        at Socket._write (net.js:552:19)
        at Socket.write (net.js:511:15)

To fix the `Error: write EPIPE` error, check whether the stream or socket you're writing to is still active and running before attempting to write data. Use a `try-catch` block to catch the error and then take appropriate action, such as closing the stream or logging the error.

## Additional common Node.js errors <a name="additional-common-node-js-errors">

Here are a couple of additional Node.js errors that don’t fit into one of the categories we’ve already discussed, but that you’re likely to encounter sooner or later if you have not already.

### `.find is not a function` <a name="find-is-not-a-function">

The `.find is not a function` error occurs when you call the `find()` method on a data type that is not an array:

```javascript
const data = {
  x: 5,
  y: 10,
  z: 15,
};

data.find(el => el > 1 );
```

In this example, the `find()` method is being invoked on an object. Since the `find()` method only works on arrays, the following error will be thrown:

```javascript
TypeError: arr.find is not a function
```

To resolve this error, ensure that you invoke the `find()` method on a valid array:

```javascript
const data = [5, 10, 15];

data.find((el) => el > 1); // Returns 5
```

### `Uncaught SyntaxError: Unexpected identifier` <a name="uncaught-syntaxerror-unexpected-identifier">

The `Uncaught SyntaxError: Unexpected identifier` error indicates that there is a syntax error or misspelled keyword in your code that is preventing the interpreter from parsing your code correctly. This is especially common when declaring variables, classes, or methods and mistakenly using an uppercase letter instead of a lowercase letter for the keyword:

```javascript
Let name = "same"; // L should be lowercase l

Const age = 20; // C should be lowercase c
```

To resolve the `Uncaught SyntaxError: Unexpected identifier` error, navigate to the line where the error occurred and ensure that keywords are spelled correctly. Also look for missing symbols like commas, colons, brackets, or parentheses. By identifying the source of the error, you should be able to easily resolve it.

## Conclusion

Errors are an integral part of what makes us good developers. By understanding them and why they occur, we gain a deeper understanding of the programming language or environment we are working on. 

In this article, we reviewed some of the most common Node.js errors and discussed how to fix them. I hope this article has helped you to understand Node.js and JavaScript a bit better. Happy hacking!

---

## 200’s only  Monitor failed and slow network requests in production

Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third party services are successful, [try LogRocket](https://lp.logrocket.com/blg/node-signup).

[![LogRocket Signup](https://blog.logrocket.com/wp-content/uploads/2019/12/network-request-filter-2-1.png)](https://lp.logrocket.com/blg/node-signup)

[LogRocket](https://lp.logrocket.com/blg/node-signup) is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. [Start monitoring for free](https://lp.logrocket.com/blg/node-signup).