bevry / watchr

Better file system watching for Node.js. Provides a normalised API the file watching APIs of different node versions, nested/recursive file and directory watching, and accurate detailed events for file/directory changes, deletions and creations.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Watchr silently discards thrown error in listeners

soareschen opened this issue · comments

I just discovered a nasty bug in my unit test code that turned out to be caused by watchr. It appear that watchr silently discards exceptions thrown inside the listener function.

Sample source file:

var watchr = require('watchr');

var watcher = watchr.watch({
  path: '.',
  error: function(err) {
    // error not caught here
    console.log('caught error:', err);
  },
  listener: function(changeType, filePath, fileCurrentStat, filePreviousStat) {
    console.log('change event:', changeType, filePath, fileCurrentStat, filePreviousStat);

    console.log('throwing error');
    throw new Error('test error'); // will be discarded
    console.log('thrown an error'); // won't reach
  },
  next: function(err, watchers) {
    if(err) throw err;

    console.log('watching .');
  }
});

Because the listener function is bound to a domain, the errors are discarded even after returning to event loop in async operations:

listener: function(changeType, filePath, fileCurrentStat, filePreviousStat) {
  console.log('change event:', changeType, filePath, fileCurrentStat, filePreviousStat);

  process.nextTick(function() {
    console.log('throwing error');
    throw new Error('test error'); // still discarded
    console.log('thrown an error'); // won't reach
  });
},

The only way to catch an error seem to be by listening to the error event from the object returned by watchr. However even so the error handler itself cannot throw any error or they will be discarded too.

watcher.on('error', function(err) {
  console.trace('error event:', err);
  console.log('throwing error');
  throw err; // will be discard
  console.log('thrown error'); // won't reach
});

There are two problems with this bug:

  1. When an unexpected exception happens I need the program to crash immediately so that I know where is the error. Unit test frameworks like mocha and should also rely on propagating errors to handle assertion failures.
  2. Watchr uses taskgroup which uses domain to catch all listener errors. This could cause unexpected behavior when users also create outer domain with the expectation to catch all errors including the ones inside the listeners.

Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.

v3.0.0 which is just released is a major rewrite. During the rewrite I discovered very much the same things as you were talking about and the error handling has been revised. So this issue should now be considered resolved - happy to reopen if it isn't. 👍

Sorry for the late response on this, 2014 and 2015 were hard years for me!