How to catch server-side exceptions from a client-side mongo update? [closed]

We still have 1 collection where we use pub/sub + mini-mongo and allow client code to do updates via allow/deny.

How can we catch errors on the server?

When the client code does <collection>.update(), it fires an RPC to the server where the endpoint calls our allow/deny routines to validate. Finally, the endpoint calls Mongo update. Our problem, the update can fail (rarely) it throws. What we want is to catch this exception, log it, and possibly fix it, and re-throw if we can’t fix it.

Any suggestions about how we can hook or monkey patch the server endpoint?

1 Like

Isn’t the error present in the callback? (It can’t be there synchronously because of the client-server communication.)

Thanks for your kind reply. My question was possibly unclear.
The update is initiated from the client as you noted. We want to catch the exception when it is thrown on the server… before replying to the client.

I don’t think it’s possible, at least in a non-hacky way. Why do you want to keep the direct Mongo operations instead of switching to using methods?

Long term plan is to switch, but this particular collection has some non-trivial code that needs to be redone first b/c it assumes the synchronous behavior of mini-mongo.

Have you tried passing a callback function into the Mongo operation? It can be added as the last argument, similar to Method.call callbacks

I don’t get the problem then. Minimongo stays “sync” (through simulations) even in methods. Maybe you could post some example code to present the problem?

Thank you both for trying to understand our problem. Sorry for the delay.
I am not keen to explain exactly why we are not ready to switch to RPC for updates and away from mini-mongo. Simply understand that we pub/sub and update.

With that starting point, if the server throws, the client can NOT get an error message and the server logs a bunch of useless noise in the console. What happens is that mini-mongo will get an update from the server and “roll back” the update that failed. But the only error message is the generic “Internal server error [500]”.

We are not trying to give the client a smarter error message. We are hoping to “fix” (if possible) the problem on the server. We need a way to catch the exception on the server.

Thanks!

Hmm… you’d probably need to set up a messaging service between client and server. RocketChat has some packages for these kinds of things.

Alternatively, you can probably do something simpler via connectionId and regular pub/sub:

  • On server, when there is an error, you insert a document into an “Errors” collection with a reference to the connectionId
  • On the client, you subscribe to the error documents with the connectionId

You can probably “burn” the documents on the first subscribe for some extra security

Two solutions I have in mind:

  1. APM
  2. Override the default error handler of Meteor to catch and log the errors

Nice idea, Max, but the goal is not to improve the error message to the client, so much as to prevent/correct an error in the first place.

rjdavid, I’m curious how you propose to use APM in this context.
But, more what I’m looking for is #2. How do we override the default error handler?

Errors are being logged by the Galaxy APM or MontiAPM. So any error should be logged by these APMs.

Custom error handlers:

// Meteor debug handler
const originalMeteorDebug = Meteor._debug;
Meteor._debug = function _debug(message, stack) {
  // do anything about the debug message and stack here

  // call the original debug handler here
  return originalMeteorDebug.apply(this, [message, stack, arguments]);
};
1 Like

Sounds like something messy going, maybe best to post some code samples

rjdavid, We can see the errors in APM and in the general log. We have no problem re logging. It is a question about trying to catch and handle the error.

Meteor._debug is a great tip that opens up some ideas we can chase down. Thanks!

Max, nothing tricky. This is a very typical code pattern with nothing surprising. We can wonder why the framework doesn’t give us an easy hook like beforeUpdate/afterUpdate (like allow/deny), but let us also acknowledge, using client-side update is a deprecated pattern.

Client user code calls update.
Meteor framework makes RPC call to update
The mongo call throws
The Meteor framework returns generic “internal error” to client

We just want a sanctioned way to hook or monkey patch the meteor framework’s rpc call.

It’s not clear why an error is being thrown. Maybe there’s another strategy here

We know which error and why the error is thrown. We also think we know how to fix the error. Thus we need a hook so we can run some code.
The RPC that gets called is (collection)/update.
One possibility is to patch that endpoint… (how?) Or, perhaps folks know of another way to hook the client-side update when it reaches the server.

You can patch the method that Meteor creates for that collection just on the server, or the actual collection.update() function on the server

The quick and dirty way would be to patch it on the Meter.methods() function and look for when the specific function is being called, or maybe go into deep apis and patch the method function that is registered. IIRC there’s a method hooks package for this.

Or maybe you can do Meteor.isClient/Meteor isServer in the isomorphic code to outline some specific error handling as well :man_shrugging:

We’ve been experimenting with this:

Meteor.server.method_handlers["/mycollection/update"] = function(selector, modifier, options, callback){...}

This definitely “works”, but it is a nasty hack.