DEV Community

Remy Sharp
Remy Sharp

Posted on • Originally published at remysharp.com on

Smarter throwing

With async/await becoming standard procedure for a lot of my code, I find myself wrapping blocks of code in try/catch to ensure I'm handling errors properly.

As a result of this, I also try to make my errors a little more useful at the same that I want to show you in this mini post.

The example

I have large validation process that runs through a series of statements and checks for particular problems and rules.

Each validation rule is run and if it fails, it throws with a message, such as:

export function validateFakeExample(token, scope) {
  if (token.text !== 'PRINT') return;

  const next = scope.peekNext();
  if (next.name !== AT) {
    throw new Error('Parser error, PRINT keyword should be followed by AT');
  }
}

Enter fullscreen mode Exit fullscreen mode

My main function runs each of the validation rules all encapsulated inside of a try/catch because I also want to capture additional metadata that will help my user understand what caused the error.

So in my wrapping catch I have something like this:

} catch (error) {
  const message = error.message + `, "${token.text}" at: ${token.pos + 1}`;
  throw new Error(message);
}

Enter fullscreen mode Exit fullscreen mode

This way, when the error is given back to my user, they'll see:

Parser error, PRINT keyword should be followed by AT, "INK" at: 10

Enter fullscreen mode Exit fullscreen mode

Actually I use this pattern a lot, to catch the source error, interpret it, and throw new Error to help me better understand what was going on.

Except it can be smarter.

Being smart

When I call new Error a brand new error object is created. At this point a few things happen, specifically the stack is captured. A stacktrace is incredibly useful for debugging to trace back to the source of the problem.

Except, because I generated a brand new error, my stacktrace will originate from within the catch, which is helpful to a certain degree, but could be a lot more useful.

I could do something with the stack. At times I've added a console.log(error.stack) in the catch which I can go searching my logs for.

What I should do is instead of throwing a new Error, I can simply modify the original error.message property (🤦 why did it take me that long).

So now my code looks like this:

} catch (error) {
  error.message += `, "${token.text}" at: ${token.pos + 1}`;
  throw error;
}

Enter fullscreen mode Exit fullscreen mode

My custom error message is passed by to the user (normally me) and my full stacktrace is retained.

Originally published on Remy Sharp's b:log

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more