In previous blogs, we have covered executing N1QL from JavaScript functions, processing documents through iterators, and manipulating data.

We now move onto handling errors from N1QL statements.

Error handling

When an error of any nature is encountered, the jsevaluator by default will halt the function execution and return an error:

In this particular case, the second INSERT will fail because key k10 already exists:

You don’t have to stick to the default behaviour, JavaScript allows to catch errors and handle them:

In this case, the function doInsert() returns failure because key k10 already exists.

Return vs throw

The catch block can be used to handle the failure in whichever way is useful for your business logic.

The available options boil down to 1) take some evasive action and continue execution, 2) return early with success, and 3) return early with failure.

The difference between success and failure is simply using return to return a value as in the example above vs throw to return an error.

The difference between the two is important, because if you choose to return a result, the caller request will continue execution. While if you throw an error, the whole request will fail with the error, so do be mindful about which you want to use, because it will make the difference between your request working correctly and misbehaving.

Returned expression

The second thing to bear in mind is that, whether you return or throw an error, you may very well want to give meaningful information.

Consider the following code:

This will fail with something like:

Much like the previous example, what we gather from this is that err is an object, and is returned in the reason field.

However, if you amend the throw statement like so:

The doInsert() function will now throw a string and not an object:

The err object is now marshalled into a string, and all of a sudden, your error is not as legible.

This applies to return too: in particular, by default err contains strings containing marshalled JSON objects.

For instance:

Returns:

If you want to obtain a nice returned value, you have to parse the error.message object before returning it:

Which yields:

And if you want to include the stack too, you have to construct a new object like so:

Which yields:

The moral of the story is: be mindful of how you return your error, and be mindful how you format it.

Conclusion

Over the course of several blogs, we have covered executing N1QL, processing documents and manipulating data, and handling errors.

Next in the series, we’ll move to prepared statements.

Author

Posted by Marco Greco, Software Architect, Couchbase

In a previous life, Marco used to be CTO, radiation physicist, software architect, sysadmin, DBA, trainer and general handyman at Italy's largest radiation theraphy practice. Having switched career and country, he spent more than two decades in various support and development positions in Informix first and IBM later, before finally taking the plunge and joining Couchbase, to help them make gold out of N1QL. He holds several patents and has authored open source projects of his own.

Leave a reply