How to handle stream errors?
© https://nodejs.org/en/

How to handle stream errors?

If a stream error is not handled, it can crash your application.

ByMario Kandut

honey pot logo

Europe’s developer-focused job platform

Let companies apply to you

Developer-focused, salary and tech stack upfront.

Just one profile, no job applications!

This article is based on Node v16.14.0.

Streams are a built-in feature in Node.js and represent asynchronous flow of data. Streams are also a way to handle reading and/or writing files. A Node.js stream can help process large files, larger than the free memory of your computer, since it processes the data in small chunks.

Streams in Node.js

💰 The Pragmatic Programmer: journey to mastery. 💰 One of the best books in software development, sold over 200,000 times.

This is the third article of a series about streams in Node.js. It explains how to handle errors in streams.

Streams in Node.js

Handling stream errors

Building robust Node.js applications requires dealing with errors in proper way. Have a look at the article series about Node.js errors for a refresher on errors - Errors in Node.js.

The most important event emitted by a stream is the error event. If this error event is not handled, it can crash your application. Hence, errors have to be handled when working with streams.

Error event handler

To handle error events attach an event handler directly on the stream.

Let's create a PassThrough stream and add event handlers.

Create a file.

touch streams-error-emit.js

Add code.

const { PassThrough } = require('stream');

const passThrough = new PassThrough();

passThrough.on('error', err => {
  console.error('passThrough encountered an error:', err);
});
process.stdin.on('error', err => {
  console.error('stdin encountered an error:', err);
});
process.stdout.on('error', err => {
  console.error('stdout encountered an error:', err);
});

process.stdin.pipe(passThrough).pipe(process.stdout);

passThrough.emit('error', new Error('Somewthing went wrong!'));

When you run the code with node stream-error-emit.js from the CLI the error will be first emitted from PassThrough, and then handled by it with throwing the error message passThrough encountered an error: Error: Somewthing went wrong!. Now try to remove the error handling for the PassThrough stream, just for fun. The example will crash with unhandled exception, exiting the program early and with a status code of 1.

Handling errors this way works and prevents your application from crashing. However, it can be unmanageable to attache these event handlers for every stream when working with the pipe method.

Handling errors with the pipeline method is much cleaner and manageable. The callback is called when the pipeline is fully done and can handle errors.

pipeline(
  // source stream,
  // transform or other streams,
  // destination stream,
  (err) => {
      if (err) {
        console.error('Pipeline failed.', err);
      } else {
        console.log('Pipeline succeeded.');
      }
    }
);

finished()

The finished() function gets triggered when a stream is no longer readable, writable or has experienced an error, or a premature close event. Handling errors with finished() is another option and was added in Node.js version 10. It takes a stream with options as first, and a callback as second argument - stream.finished(stream[, options], callback)-

const { finished } = require('stream');

const rs = fs.createReadStream('archive.tar');

finished(rs, err => {
  if (err) {
    console.error('Stream failed.', err);
  } else {
    console.log('Stream is done reading.');
  }
});

The finished function is especially useful in error handling scenarios, where a stream is destroyed prematurely (like an aborted HTTP request), and will not emit end or finish.

The finished API also provides a promise version:

const { finished } = require('stream/promises');

const rs = fs.createReadStream('archive.tar');

async function run() {
  await finished(rs);
  console.log('Stream is done reading.');
}

run().catch(console.error);
rs.resume(); // Drain the stream.

TL;DR

  • Unhandled stream errors crash the application.
  • One option to handle stream errors is to attach an event handler and listen to error events.
  • Another option to handle errors is the finished function. It is especially useful in error handling scenarios, where end or finished are not emitted.
  • The pipeline method provides an easier way to handle error events.

Thanks for reading and if you have any questions, use the comment function or send me a message @mariokandut.

If you want to know more about Node, have a look at these Node Tutorials.

References (and Big thanks):

HeyNode, Node.js - Streams, MDN - Streams

More node articles:

Getting started with Webpack

How to list/debug npm packages?

How to specify a Node.js version

How to create a web server in Node.js

How to dynamically load ESM in CJS

How to convert a CJS module to an ESM

How to create a CJS module

How to stream to an HTTP response

How to handle binary data in Node.js?

How to use streams to ETL data?

How to connect streams with pipeline?

How to handle stream errors?

How to connect streams with pipe?

What Is a Node.js Stream?

Handling Errors in Node (asynchronous)

Handling Errors in Node.js (synchronous)

Introduction to errors in Node.js

Callback to promise-based functions

ETL: Load Data to Destination with Node.js

ETL: Transform Data with Node.js

ETL: Extract Data with Node.js

Event Emitters in Node.js

How to set up SSL locally with Node.js?

How to use async/await in Node.js

What is an API proxy?

How to make an API request in Node.js?

How does the Event Loop work in Node.js

How to wait for multiple Promises?

How to organize Node.js code

Understanding Promises in Node.js

How does the Node.js module system work?

Set up and test a .env file in Node

How to Use Environment Variables in Node

How to clean up node modules?

Restart a Node.js app automatically

How to update a Node dependency - NPM?

What are NPM scripts?

How to uninstall npm packages?

How to install npm packages?

How to create a package.json file?

What Is the Node.js ETL Pipeline?

What is data brokering in Node.js?

How to read and write JSON Files with Node.js?

What is package-lock.json?

How to install Node.js locally with nvm?

How to update Node.js?

How to check unused npm packages?

What is the Node.js fs module?

What is Semantic versioning?

The Basics of Package.json explained

How to patch an NPM dependency

What is NPM audit?

Beginner`s guide to NPM

Getting started with Node.js

Scroll to top ↑