30 Days of Node

Day 5 : All about errors in nodejs

30 Days of Node | Node.js Tutorial series



What are errors ?

Errors are any issue that arises unexpectedly and cause our program to not function properly , or halt its execution.

Errors in node.js

An error object in node.js does not specify any circumstances under which the error occured but error object does capture a stack trace which details the point in the code where the error was instantiated and may provide error description. All errors generated by node.js are either instantiated from error class or are intance of error class.

Properties of errors in node.js

  1. new Error(message) : It is used to create a new error object. It also sets error.message property to the text specified.
    											
    const err = new Error('This is an error message');
    											
    										

  2. error.message : It shows the description of the error. It is set using new Error(msg) property. Mostly , the message "msg" comes in the first line of the error's stack trace . An example is shown below :
    											
    //here error.message property is set to the string provided.
    const err = new Error('This is an error message');
    console.error(err.message);
    //Output will be :
    //This is an error message
    											
    										

  3. error.code : This is a string label which is used to identify the type of error. It specifies errors in the form of node.js error codes .
  4. error.stack : It returns a string in which details are provided about where in the code the error was instantiated.
  5. Error.captureStackTrace : This is used to create a .stack property on the target object which returns the location in the code where Error.captureStackTrace() was called. It returns the data in the form of string.
  6. Error.stackTraceLimit : This property specifies number of stack frames captured by stack trace. It can be any valid JS number however 10 is the default value. If set to a non-number or negative number , then stack trace will not return any frames.

Error propagation and interception in node.js

In node.js , we are having several mechanisms for error propagating and handle those propagated errors while the application is in its running state. However the way in which these errors are reported and handled completely depends upon the type of error and API style.

  1. Synchronous APIs : These are those APIs which uses blocking method that does not accept a callback function and uses throw to report errors.
  2. Asynchronous APIs : Errors which occurs in asynchronous APIs can be reported in multiple ways as shown below :
    • Errors can be routed to the object's error event if an asynchronous event is called on an object.
      Note : Don't worry if you don't understand the snippet. Just try to grasp the concept here.

      													
      connection.on('error', (err) => {
      		//This is the error event which is used
      		//to handle the error properly
      		console.error(err);
      });							
      													
      												

    • Asynchronous methods in node.js accepts an error object passed as the first argument given that method should accept callbacks. These errors are handled in the following way :

      													
      //Reading a File Asynchronously using nodejs
      //if any error occurs such as file not found
      //we don't have permissions , etc
      //then an err message will be console.
      //otherwise data will be printed
      var fs=require('fs');
      
      fs.readFile('message.txt', (err, data) => {
      	if (err) 
      		return console.error(err);
      		
      	console.log("Content :  " + data);
      });
      							
      													
      												

    • Very few asynchronous methods still use throw to raise exception which can further be handled using try/catch block. (Not recommended)

Node.js styled callbacks

Node.js methods follows a idiomatic pattern which is knows as Node.js style callback . Following this pattern , we pass the callback function as an argument to the method. When the execution of the operation is completed or an error is raised then the callback function is called with error object if there exists any error object otherwise the first argument is passed as null .

								
const fs = require('fs');

function nSCallback(error, data) {
  if (error) {
    console.error('Error : ', error);
    return;
  }
  console.log(data);
}
fs.readFile('file_that_exists', nSCallback);
fs.readFile('file_does_not_exists', nSCallback);						
								
							

Why not try/catch

We cannot use try/catch mechanism to intercept the errors generated by asynchronous APIs.
Note : The snippet Given below is invalid

								
//Invalid Snippet
//An asynchronous operation which will generate error
try {
  async_method('invalid_arguments_generate_error', (err, data) => {
    if (err) {
      throw err;
    }
  });
} catch (err) {
	console.error(err);
}							
								
							

This is a very common mistake with beginners. This will not work because the method is asynchronous. The time by which the callback will be called , surrounding code already completed its execution and exited. Throwing an error inside the callback can leads to the crashing of node.js process in most of the cases.

About errors

In node.js applications , mostly all the errors belong to one of the mentioned categories :

  1. Standard javascript errors :
    • < URI > error : This error is thrown when a global URI handling function is misued.
    • < Eval > error : This error is thrown when the call to eval() fails.
    • < Type > error : This is a subclass of error which shows that the argument provided is not of allowed type.
      for e.g. passing an object where a string is expected would be considered a TypeError.
    • < Range > error : This is a subclass of error which shows that the argument provided was not within the range of acceptable values.
    • < Syntax > error : This is a subclass of error which indicates that the code written is not of valid Javascript.
    • < Reference > error : This is a subclass of error which signifies that an attempt is made to access a variable which is not defined. These are very common typos or broken code .
  2. System errors : This type of errors are generated when the exception occurs during the run time of the program. They are generated when the application violated some constraints of operating system.
    Properties of system errors :
    • error.code : This is a string which represents and error code. some common examples include EACCES , EADDRINUSE , ECONNREFUSED , etc .
    • error.port : This is a number which represents the connection's port which is unavailable.
    • error.address : This is a string which represents the address to which the connection failed.
    • error.path : This is a string which represents the relevant invalid pathname .
    • error.syscall : This is a string which represents the failed syscall .
    • error.errno : This property can be a number or a string. If number , the value will be negative which corresponds to the error code. If string , it is same as error.code .
  3. User-specified errors : This type of errors are generated by application code.
  4. Assertion errors : This type of errors are raised by assert . This type of errors are special case of errors which occurs when an exceptional logic violation is detected in node.js that should never occur.

Summary

In this part of the node.js series 30 days of node we learned about errors . We learned what are errors and errors in node.js and properties of errors in node.js.
We also learned about error propagation and interception in nodejs , what is the concept of node.js styles callbacks and why it is better to avoid try/catch while using asynchronous functions. Lastly we learned about the 4 categories most of the errors belong to which are Standard javascript errors , system errors , user-specified errors and assertion errors .



Repository
Get the code on