Search code examples
javascriptmeteormeteor-methods

Meteor.call raises exception even with a callback function


I have the Meteor method:

Meteor.methods({
  orderStatusUpdate: function(orderId, status, note) {
    check(orderId, String);

    var statusData = {
      status: status,
    }
    if (note) {
      statusData.statusNote = note;
    }
    check(statusData, SchemaCompiled.orderStatus);

    Collections.orders.update({_id: orderId}, {$set: statusData});
  }
});

with custom validation on field statusNote:

custom: function(){
  if (someCondition) {
    return 'required';
  }
  return false;
}

My issue is that even with a callback function defined:

Meteor.call('orderStatusUpdate', orderId, orderStatus, note, function (error, result) {
  // doing something
}

the Exception is logged to Console:

Exception while simulating the effect of invoking 'orderStatusUpdate' errorClass {message: "Match error: Note is required", path: "", sanitizedError: errorClass, errorType: "Match.Error", invalidKeys: Array[1]} Error: Match error: Note is required

As I understand the exception is raised when I call check(...).

How can I catch this exception to properly show it to the customer?

BTW, the callback function also is called with the error variable set.


Solution

  • The raised/logged exception has nothing to do with the callback or lack thereof.

    If the method is defined in a shared folder (that is evaluated by both the client and the server), a stub will be run on the client. If it throws anything, the error is normally caught and logged to console.

    The callback is only related to the server-side run.

    You have a number of ways to handle this:

    1. Define the method server-only (in the server folder).

      This will make the method run on the server only, so the error will be received on the client.

    2. Catch it on the client and do something about it, as @ChristianFritz suggested.
    3. Use a (currently) undocumented feature (throwStubExceptions) that, in case the stub throws an exception, throws the exception and prevents the server method from being called:

      On both the client and the server:

      Meteor.methods({
        thrower: function() {
          throw 'catchMe!';
        }
      });
      

      Then, on the client:

      try{
        Meteor.apply('thrower', [], {throwStubExceptions: true}, function(err, res){
          console.log('err!', err);
        })  
      } catch(e) {
        console.log('caught', e);
      }
      

      This code will catch the error and log caught catchMe!, and the method will not be called on the server.