Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non existing property: EventEmitter memory error instead of proper error message

In a NodeJS 6.10.2/SailsJS 0.12.13 based JavaScript application I experience since several months a strange error behavior.

In a Sails controller, I try to retrieve a property of a literal object:

console.log(someObject.someProperty);
console.log("I am still here!");

However, in my case someObject is undefined. So, I'd expect to get an error like 'Cannot read property someProperty of undefined.' - and then either Node.js to stop completely or the code to go on (with the next console.log).

Instead, the code simply stops executing at that point and I get a strange warning: "(node:4822) Warning: Possible EventEmitter memory leak detected. 11 close listeners added. Use emitter.setMaxListeners() to increase limit." It is however, unpredictable how often this error occurs. Somethings only once, somethings about 20 times right after each other.

What I found out so for is that it is somehow connected to the question whether there was already a response or not. Consider the following:

mySailsControllerFunction: function(req, res) {
    console.log(someObject.someProperty);
    console.log("I am still here!");
    res.json({"foo":"dahoo"});
   }

This will result in Sending 500 ("Server Error") response: ReferenceError: someObject is not defined - exactly what I expect.

However, now I first send some response and then trying to access my non existing property, turning the code into:

mySailsControllerFunction: function(req, res) {
        res.json({"foo":"dahoo"});
        setTimeout(function () {
          console.log("Yeah!");
          console.log(someObject.someProperty);
          console.log("I am still here!");
       },1000);
}

then I often get simply nothing: 'Yeah!' displayed, but nothing comes afterwards. The event listener error is sometimes there, sometimes not. Very strange.

Additionally, and strange enough, the problem seems to be somehow connected to the time passed since the start of Sails. I put the code you see above inside a Sails controller function which is called immediately after the clients re-connect. I then played around with the timeout values, restarting the Sails server several times. Outcome: If I set the timeout to 1s, in 4 of 5 tests, I will get the correct error behavior. For 10 seconds it is about 50%, for 30s the error will always be ignored without any console output.

However, if I put my test code outside of the Sails controller, I always get the correct error behavior by Node. So, I'm quite sure this is a wrong behavior of Sails, not Node.

like image 559
cis Avatar asked Jul 17 '17 06:07

cis


1 Answers

Disclaimer: I don't know Sails. So it may or may not be related, but my answer may offer a clue.

From the Sails documentation: http://sailsjs.com/documentation/reference/response-res/res-json

This method is terminal, meaning it is generally the last line of code your app should run for a given request (hence the advisory usage of return throughout these docs).

Thus, when you use res.json({"foo":"dahoo"});, Sails probably sends the response back to the client, closing the call sequence, which, if it uses Promises or some other async mechanism, may kind of "swallow" further code, as also suggested in an above comment. This is probably internal coding in Sails, so it's not immediately obvious from the outside WHY your second code block specifically doesn't work.

So you should stick to the first pattern: access your property first, and put res.json() at the end of the controller function.

like image 177
transient_loop Avatar answered Oct 20 '22 03:10

transient_loop