Node.js Error Handling

Node.js Error Handling – ERR_BUFFER_TOO_LARGE

There are many possible errors in Node.js, so today we’ll continue our detailed Node.js Error Handling series by looking at one of the assorted System Errors Node produces, ERR_BUFFER_TOO_LARGE. Node throws a System Error when an exception occurs within the program’s runtime environment, and such errors are typically an indication that there was an operational problem within the application. An ERR_BUFFER_TOO_LARGE error indicates that an attempt was made to instantiate or allocate a Buffer object of a size exceeding the current maximum (typically 2,147,483,647, or the maximum size of a 32-bit signed binary integer).

In today’s article examine the ERR_BUFFER_TOO_LARGE system error by looking at where it resides in the overall Node.js Error Class Hierarchy. We’ll also look at some functional code samples illustrating how direct Buffer object manipulation doesn’t allow method calls that may directly throw ERR_BUFFER_TOO_LARGE errors. Instead, certain modules (like zlib) can potentially generate such errors in extreme circumstances. Let’s dig in!

The Technical Rundown

Most Node.js errors inherit from the Error base class, or extend from an inherited class therein. The full error hierarchy of this error is:

Full Code Sample

Below is the full code sample we’ll be using in this article. It can be copied and pasted if you’d like to play with the code yourself and see how everything works.

When Should You Use It?

As we discussed in our ERR_BUFFER_OUT_OF_BOUNDS article last week, the Buffer class was added to early versions of Node.js provide simple means of reading and manipulating streams of binary data. More recently, JavaScript ES6 (ECMAScript 2015) introduced the TypedArray object to handle binary data buffers. Therefore, modern Node.js versions have adapted the Buffer class to focus on implementing a more optimized Uint8Array API.

In modern Node.js versions the Buffer class constructor has been deprecated, so the process of actually creating buffers would ideally use the Buffer.from(), Buffer.alloc(), and other similar methods. For our example code we’ll use both techniques, starting with a direct instantiation using the deprecated new Buffer(...) constructor, and afterward we’ll also use the Buffer.alloc() method.

Our first test method is instantiateBuffer(size), which uses the deprecated new Buffer(size) constructor to instantiate a new buffer object:

We’ll test out creating three different buffer sizes, 1, kMaxLength, and kMaxLength + 1:

kMaxLength is exported from buffer, which is actually imported from process.binding('buffer') and represents the maximum size of a 32-bit signed integer (2,147,483,647), which is typically used in Node to limit the sizes of many objects, including buffers. Executing these three different size tests produces the following output:

As you can see, even though the direct new Buffer(...) constructor is deprecated it still functions and allows us to create buffer objects of size 1 and kMaxLength. However, a size of kMaxLength + 1 produces an error, but, surprisingly, it’s an ERR_INVALID_OPT_VALUE rather than an ERR_BUFFER_TOO_LARGE.

Let’s try allocation rather than direct instantiation:

Our allocateBuffer(size) method performs really the same process as instantiateBuffer(size), but through the Buffer.alloc(size) method instead of new Buffer(size). Once again, we’ll test it using the same trio of size allocations:

Executing these tests produces nearly identical output as our direct instantiation test:

Hmm, yet another ERR_INVALID_OPT_VALUE. We can actually see why these behave so similarly by digging into the Node buffer.js module code. First, we can see inside the direct new Buffer(...) constructor that, if the first argument is a number, it simply passes execution to the Buffer.alloc(...) method on our behalf:

The Buffer.alloc(...) method (along with nearly every other Buffer method in the module) starts by invoking the assertSize(size) method:

Inside assertSize(size) we see the final statement that our tests were hitting to throw the ERR_INVALID_OPT_VALUE:

As you can see, the Buffer module actually performs checks against the kMaxLength value for all Buffer size allocations before it actually creates any buffers or does any processing. Therefore, as previously mentioned, it is impossible to throw an ERR_BUFFER_TOO_LARGE error directly from using the Buffer module. However, it should be noted that some other Node modules may be capable of producing ERR_BUFFER_TOO_LARGE errors under certain circumstances. At present, the only library that can throw such errors in zlib.

Airbrake’s robust error monitoring software provides real-time error monitoring and automatic error reporting for all your development projects. Airbrake’s state of the art web dashboard ensures you receive round-the-clock status updates on your application’s health and error rates. No matter what you’re working on, Airbrake easily integrates with all the most popular languages and frameworks. Plus, Airbrake makes it easy to customize error parameters, while giving you complete control of the active error filter system, so you only gather the errors that matter most.

Check out Airbrake’s error monitoring software today and see for yourself why so many of the world’s best engineering teams use Airbrake to revolutionize their exception handling practices!