Error handling strategy: UI instead of console.log()

What is the best strategy to handle errors in a Meteor/React app?

For now, I do throw new Meteor.Error() in both client and server code, but I want to capture these errors and display in the webpage - and not just console.

I do have React Error Boundaries (https://reactjs.org/docs/error-boundaries.html) in place, but they don’t handle errors from events or timeouts by design.

1 Like

My recommendation is to do the absolutely most basic approach, which is to simply override console.log and console.error to do the behaviour you need. You’ll observe situations like this:

where code by the framework authors (Meteor or React) might have a good reason to not use the framework, and they almost always fall back on a console method or somesuch to report the exception.

The most important gotcha with any exception handler is that you should not throw an exception inside your exception handler. You should very simply store your exception message somewhere, and then render it like any other conventional piece of data.

Not to get too metaphysical, but if you have a better message to send than the one stored in the error itself, use that message in the error.

Or don’t throw errors! Because of its idiosyncratic adoption of fibers, throwing errors in methods works fabulously well, but will seem really alien to most node people, and certainly not the way React expects to handle errors.

Indeed, what really is an exception in the React part of your app? Just to clarify why react does things this way: an exception in UI code is pretty much always a bug, not an “exception.” Like you should never throw a 403 not authorized exception when you click a button - don’t render that button, or navigate a user directly to a screen that says not authorized. Aside from null reference exceptions, which are clearly bugs you shouldn’t report to the user.

Right, lets take a practical example:

In a server side validation (SimplSchema) I do:

    'ldap.lookupInitials'(initials) {
      try {
        new SimpleSchema({
          initials: {
            type: String,
            min: 5,
            max: 5,
            required: true,
          },
        }).validate({ initials });
      } catch (err) {
        throw new Meteor.Error('validation error', err);
      }

  ...

So I can recapture the error at the Meteor.call client side with:

      Meteor.call('ldap.lookupInitials', user.username, (err) => {
        if (err) {
          throw new Meteor.Error('ldap.lookupInitials failed', err);
        }

   ...

But I wonder if there was a simple way to do a ‘rescue’ of the error to display some nice UI, and stop or continue the rendering depending on the error type.

(btw, I do note that err objects are not good for passing across DPP, there is probably a useful string in that object somewhere)

err.message is probably what you’re looking for:

Thanks Rob, that was the easy part :o) - how about a blog entry on Meteor error handling best practices ?

Maybe start by wrapping Meteor.call? You can create a wrapper (a decorator) that checks if any Meteor.call calls generate an error?

let meteorCall = Meteor.call;
Meteor.call = function() {
  meteorCall.apply(Meteor, arguments);
  // ...
}

You could, for example, set a reactive variable lastError to the last error received from a Meteor.call, and clear it after a short delay?