Node.js Errors — Changes you need to know about

This post was written by Michael Dawson who is a Node.js Runtime Tech Dev @ IBM, #nodejs collaborator and CTC member. He originally posted this piece on the Nodejs @ IBM blog.

Summary

Changes are coming to Errors thrown by the Node.js runtime. These changes started showing up in Node.js 8 and will continue to flow in during Version 9. This will impact any user whose code parses the message strings.

What and Why ?

First off why are these changes needed and what are they? Until recently most of the Errors thrown by Node.js only had a message associated with them. If you wanted to have your code take a specific action based on the Error, you would have had to compare the message string to a known value. The result might be something like:

Code like this should not be very common as in most cases when you get an error from Node.js it’s more likely that your code will simply log/display the message and then branch to a common recovery path. However, in the cases where it was necessary, you end up relying on the specific error message string.

Now you might have noticed that there is a typo in the message used in the example above. Well, that happens in the Node.js code base as well. The problem is when we notice the typo and want to fix it we currently mark the change as SemVer major. This means the change will only be included in the next major release and can’t be backported to older versions. In the case of a typo that may not be a big deal, but if we have a message that is wrong or misleading it is more of a concern.

The hard dependency on the message string also poses a challenge for internationalization. Node.js has made good progress on this front through the addition of ICU and APIs to be able to internationalize application code. If/when we want to take the next step and allow internationalization of the error messages returned by Node.js, we need to allow the specific Error to be identified without using the message. This is necessary because once localized, the message itself could change based on the locale set for the user.

The changes being made are to add a ‘code’ to all of the error objects thrown by the Node.js APIs. These codes are being documented in the API docs in https://nodejs.org/dist/latest-v8.x/docs/api/errors.html#errors_node_js_error_codes. (If you generate docs for master you will see a larger list).

This should allow the earlier example to be re-written as follows:

with the result being that if/when the message changes in the future, the example code won’t be affected as the error code remains unchanged.

Along with the addition of the code, the name of the Error is also being set to include the error code. For example, for the common errors:

  • Error [error-code]
  • TypeError [error-code]
  • RangeError [error-code]

The result is that the toString() for the error will be in the following format:

  • Error [error-code]: message
  • TypeError [error-code]: message
  • RangeError [error-code]: message

Once Error codes are in place the plan is to be able to update message strings without having to mark the change as SemVer major. There is still some discussion around when we will be ready to do that. If you’d like to read some of the back and forth on this discussion check out this issue: https://github.com/nodejs/node/issues/13937.

What you need to do

  • For the code bases you maintain look for instances where you are depending on the message string for Errors.
  • In cases where it is not absolutely necessary, remove instances where you depend on the message string content.
  • As error codes are added, update your code base to use the error code instead of the message. In cases where you need to support multiple versions of Node.js you can do something like this:

The initial check to see if the error code exists is to make sure we only accept a match on the message if there is no code on the error. This avoids any possibility of matching on a different error that might have the same message.

Contributions still needed

While there has been good progress on doing the conversion (many thanks to those who have already stepped up to do conversions) there is still work to do.

Progress on converting over to the new approach is being covered under this issue created by James Snell: https://github.com/nodejs/node/issues/11273. He also put a great guide together for how to get started in converting over Node.js files which is listed in that issue. I have used that guide to do a few conversions and it is a great starting point.

To get started find one of the files not already converted (checkbox checked) and for which no existing PR is listed. You can check for existing PRs by first validating no PR is listed for the file in https://github.com/nodejs/node/issues/11273 either in the main list or in the comments. I’d also suggest doing a quick scan of the open Node.js issues to see if there are any recent PRs covering the file you are selecting as the main issue is not always up to date. Once you open a PR, may sure to comment with the link in 11273 so that we can update the master list.

There do tend to be conflicts between PRs updating the Error messages so be prepared to have to rebase your commit (maybe even more than once) but there are currently a number of collaborators actively working to get them reviewed/landed in a timely manner.

Summary

Changes are coming to Errors thrown by the Node.js runtime. I’ve outline the what and why and provided a few suggestions on what you should be doing now to get ready. I’m also hoping some of you will be able to help complete the conversion and I am looking forward to meeting you in GitHub.

*A thank you to technical editor Simeon Vincent for reviewing this post.