Hapi-Joi error handling with custom messages

Introduction

Recently, I have ventured into the world of nodejs. Coming from XPage development, the learning curve is quite steep. I looked at several back-end frameworks express, feathersjs and Strongloop’s loopback among others. They are all fine frameworks, but the one I fell in love with was hapijs. I really like the concept of “ configuration over code” and the possibility of compartmentalization of the different parts of the application into their own separate niches. hapijs has just been updated to version 17 using async/await coding patterns, which makes most of the tutorials and guides obsolete to some extent.

In order to learn the hapi way, I decided to build a small web application with authentication. I watched Matt Harrison’s latest hapi youtube tutorials and i was hapi. Then I hit a problem with form validation. joi is a really convenient plugin for validation; it provides a JSON object as a validation result after. That’s perfect for developers, but not very user friendly for customers using your website. I googled for a solution and noticed that others also encountered this problem and I did not find a complete explanation to this problem. So I decided to share my solution with others, hopefully you will find it useful. In this post, I’ll try to explain how I came turned the joi JSON object into meaningful error messages for the end-user. Let’s begin with the basic application.

Basic hapi application

Here is the index.js file of the basic application that renders an index page and a login form. I use the Vision plugin to render handlebars templates, and the Inert plugin to server static files, such as the bootstrap 4 style sheet:

index.js

Here is the login form:

login.hbs

This results in a simple form:

Adding Joi for validation

After installing joi, it’s ridiculously easy to add validation to the submitted form. Let’s modify the POST login route and add some rules for validation:

You can see that I applied 3 rules, here (line 10–11):

  1. The username cannot be empty
  2. The username needs to be a valid email address
  3. The password cannot be empty.

If I click on the Login button with this modification, Joi throws back a general JSON error:

No matter how many rules are broken, the message is always the same canned “Invalid request payload input”. I would like to have a detailed error message for all 3 rules, so that I can inform my end user how to fix the errors. Even though, I enabled the abortEarly: false option (line 7), I only get this general message.

Luckily, there’s a solution, using the failAction:(request, h, err) => {} option. Let’s see how the POST route looks like with failAction implemented (line 13–16):

If I check my JSON joi error object now, you can see that there are detailed messages of all errors and even a validation object:

Now this is more like it, the detailed JSON object contains enough information to give detailed feedback to the end user. However, we don’t want to show raw JSON to the user; I would like to re-render the login page with easily understandable error messages. In order to achieve that, we need to intercept the error object before it reaches the user using a hapijs lifecycle function.

Adding the onPreResponse extension point method

We need to check if the response is a Boom object. All joigenerated errors use the standard Boom library, if the response is not a Boom object , we can return the response without interfering (line 4–6).

This extension point will handle not only login errors, but errors coming from other parts of the application, as well. Thus, the login errors are handled only if the response comes from the /login url and used the post method (line 8).

The request.response.details contains the detailed error messages. Using these messages, the developer needs to create the business logic to render the user friendly messages and supply this logic via an error object to the login handlebars template.

response.details

I implemented the logic by checking for the presence of the actual error messages (line 2, 10, 19) and sending an error object with boolean variables to the handlebars template. The user eventually sees these error messages:

User friendly error messages

The complete code is available at github repo: hapi-joi-error repo. Let me know if the explanation is not clear.

Like what you read? Give Csaba Kiss a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.