Search code examples
validationhapi.js

Joi validation return only one error message


I have a three field form made of a name field, email field and a textarea. I'm using Joi 4.7.0 version along with hapijs. I use the object below validate the input. I receive the data object from an ajax call. When I fill all the three fields with wrong informations I get only the message relative to the first wrong field. Like that:

"{"statusCode":400,"error":"Bad Request","message":"name is not allowed to be empty","validation":    {"source":"payload","keys":["data.name"]}}"

validate: {
      payload: {
        data: {
          name: Joi.string().min(3).max(20).required(),
          email: Joi.string().email().required(),
          message: Joi.string().min(3).max(1000).required()
        }
      }
}

For explanation let suppose to not fill the three field. I get only one message error and not the message error of the others fields. Why?


Solution

  • It happens because Joi aborts early by default.

    abortEarly - when true, stops validation on the first error, otherwise returns all the errors found. Defaults to true.

    *EDIT: Configuration has changed in hapi 8.0. You need to add abortEarly: false to the routes config:

    var server = new Hapi.Server();
    server.connection({
        host: 'localhost',
        port: 8000,
        routes: {
            validate: {
                options: {
                    abortEarly: false
                }
            }
        }
    });
    

    *See the Joi API documentation for more details.
    *Also, see validation under Hapi Route options.

    So Joi stops the validation on the first error:

    var Hapi = require('hapi');
    var Joi = require('joi');
    
    var server = new Hapi.Server('localhost', 8000);
    
    server.route({
        method: 'GET',
        path: '/{first}/{second}',
        config: {
            validate: {
                params: {
                    first: Joi.string().max(5),
                    second: Joi.string().max(5)
                }
            }
        },
        handler: function (request, reply) {
    
            reply('example');
        }
    });
    
    server.start();
    
    server.inject('/invalid/invalid', function (res) {
    
        console.log(res.result);
    });
    

    Outputs:

    { statusCode: 400,
      error: 'Bad Request',
      message: 'first length must be less than or equal to 5 characters long',
      validation: { source: 'params', keys: [ 'first' ] } }
    

    You can however configure Hapi to return all errors. For this, you need to set abortEarly to false. You can do this in server configuration:

    var server = new Hapi.Server('localhost', 8000, { validation: { abortEarly: false } });
    

    If you run the script now, you get:

    { statusCode: 400,
      error: 'Bad Request',
      message: 'first length must be less than or equal to 5 characters long. second length must be less than or equal to 5 characters long',
      validation: { source: 'params', keys: [ 'first', 'second' ] } }