Ziki
Ziki

Reputation: 1440

Prevent Sails.js from handling errors

I have a Node.js (v5.6.0, npm: v3.7.1) app running with Sails.js (v0.12.0).

When I execute this code in app.js:

process.on('uncaughtException', err => {
  //Do something
});
throw new Error();

It handles my error.

The problem is, after I load Sails, I can't catch errors with this method at all. For example, throwing an error from bootstrap.js will not be caught by the above code and I get this message in my console:

error: Bootstrap encountered an error: (see below)
error: Error: asdf
    at Object.module.exports.bootstrap.process.on.process.on.process.on.sails.async.series.callback [as bootstrap] 
    (c:\path\to\project\config\bootstrap
    .js:41:8)
    at Sails.runBootstrap (c:\path\to\project\node_modules\sails\lib\app\private\bootstrap.js:44:25)
    at Sails.wrapper [as runBootstrap] (c:\path\to\project\node_modules\sails\node_modules\lodash\index.js:3095:19)
    at Sails.initialize (c:\path\to\project\node_modules\sails\lib\app\private\initialize.js:54:9)
    at wrapper (c:\path\to\project\node_modules\sails\node_modules\lodash\index.js:3095:19)
    at c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:713:13
    at iterate (c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:262:13)
    at c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:274:29
    at c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:44:16
    at c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:718:17
    at c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:167:37
    at module.exports (c:\path\to\project\node_modules\sails\lib\app\load.js:184:13)
    at _toString (c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:52:16)
    at c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:548:17
    at c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:542:17
    at _arrayEach (c:\path\to\project\node_modules\sails\node_modules\async\lib\async.js:85:13) [Error: asdf]

I also tried to move the above code in bootstrap.js without any luck.

How can I handle any error with Sails project?

Thanks in advance!

Upvotes: 4

Views: 1662

Answers (2)

Ziki
Ziki

Reputation: 1440

For whom will come here and looks for full code, I'm posting my full code and explanation, based on @sgress454 answer:

Sails is a Web Framework that wraps your code to a web application, so it can't be never down, therefore-Sails try to handle all the errors by itself, and notify the user with 500 if needed, and continue to run the web application.

Sails app is divided into 2 steps:

  1. Before Lifting-The web application isn't accessible by anyone:

    If Sails got exception, it will quit the app, and call the lift callback with an error argument.

  2. After Lifting-The web application is accessible:

    If Sails got exception, it will quit the app, and call the lift callback with an error argument.

If Sails got exception while running the web application(after lifting), there's 2 options:

  1. Exception inside a controller action itself:

    Sails will catch this error, and respond to the user with 500.

  2. Exception wherever else:

    Sails wouldn't catch this error, and an uncaughtException will be thrown.

To handle all the above case we need to do the following:

First we want to create a global function so we can call it from wherever we are in the code:

ES 2015:

//app.js
global.handleErrors = err => {
    //do something
}

ES 5.1(and before):

//app.js
global.handleErrors = function(err) {
    //do something
}

Now we want to handle all uncaughtException's events:

//app.js
process.on('uncaughtException', handleErrors);

We can add some other events ex.:

//app.js
process.on('unhandledRejection', handleErrors);
process.on('rejectionHandled', handleErrors);
process.on('SIGINT', handleErrors);

To catch exceptions that happens in the lifting process we need to provide a callback to sails.lift function, and if the callback is called with an error we need to call the handleErrors function that we created:

ES 2015:

//app.js
sails.lift(rc('sails'), err => {
    if (err) {
        handleErrors(err);
    }
});

ES 5.1(and before):

//app.js
sails.lift(rc('sails'), function(err) {
    if (err) {
        handleErrors(err);
    }
});

And we want to handle exceptions in controllers that Sails catches and responded with 500:

//api/responses/serverError.js
module.exports = function serverError(data, options) {
    handleErrors(data);
    //lot of Sails things
};

In this way all the errors eventually will be hit the handleErrors function, so we can do there whatever we want with the error, ex. log to file, log to log management tool, send email to admin etc.

Upvotes: 3

sgress454
sgress454

Reputation: 24948

The code you posted will do exactly what it says: handle uncaught exceptions. Sails handles errors that occur during its initialization so it can attempt to exit gracefully, and attempts to handler errors that occur when processing requests so it can respond gracefully (with an error page) instead of crashing the server.

To handle errors that occur during the initialization process, provide a second argument--an error handling function--to .lift() in your app.js file:

sails.lift(rc('sails'), function handleLiftError(err, sailsInstance) {
   if (err) {
      console.log("Error occurred during sails.lift: ", err);
   }
});

You can still leave your process.on('uncaughtException'),... code in to handle fatal errors that pop up as the app is running. For instance, if you had the following in a controller action:

myAction: function (req, res) {
  throw new Error('foo!);
}

then Sails would catch that error for you and just respond with the 500 error page. But if you had:

myAction: function (req, res) {
  setTimeout(function(){throw new Error('foo!);}
}

Sails would not catch it at all--but your process.on handler would (provided you started Sails with node app.js!)

Upvotes: 1

Related Questions