Sequelize: customizable allowNull error messages

Created on 13 Mar 2014  ·  65Comments  ·  Source: sequelize/sequelize

something like this:

  var User = sequelize.define('User', {
    'email': {
      type: DataTypes.STRING,
      unique: true,
      allowNull: { args: false, msg: 'Email is required.' },
      validate: { isEmail: { msg: 'Invalid email.' } },
    },
feature

Most helpful comment

Can we reopen this?
As of 4.2.0, @sushantdhiman 's solution does not work.

      firstName: {
        type: Sequelize.STRING,
        allowNull: false,
        validate: {
          notNull: { msg: 'null is not valid' },
        },
      },

leads to

Validation error: Warning "notNull" validation has been deprecated in favor of Schema based "allowNull"
    at Promise.all.then (/.../sequelize/lib/instance-validator.js:77:15)

if firstName value is not null.

All 65 comments

My suggestion:

  • [ ] allowNull should be independent from the validation component.
  • [ ] Create a PR in chriso/validator.js adding the isNotNull validator.
  • [ ] Use the isNotNull validator as any other one.
var User = sequelize.define('User', {
  'email': {
    type: DataTypes.STRING,
    unique: true,
    allowNull: false,
    validate: {
      isEmail: { msg: 'Invalid email.' },
      isNotNull: { msg: 'The email is required' }
    }
  }
})

+1. @mickhansen what do you think?

allowNull is currently it's own type of validator, a schema validator - So it doesn't really follow the same logic as regular validators.

But yeah we can easily extend the validator in our own codebase (afaik PRs are hardly ever accepted to validator.js): https://github.com/sequelize/sequelize/blob/master/lib/instance-validator.js#L19

@fixe @nunofgs you should come hang out in IRC too, #sequelizejs @ freenode

+1, nice feature

+1 to add custom message for "allowNull".

+1

+1

+1

+1

What is the solution for this? notEmpty or notNull did not work.

travelTime: {
    type: Sequelize.INTEGER,
    allowNull: false,
    validate: {
        notNull: { msg: "Travel time is required" },
        isNumeric: true
    }
}

or

travelTime: {
    type: Sequelize.INTEGER,
    allowNull: false,
    validate: {
        notEmpty: { msg: "Travel time is required" },
        isNumeric: true
    }
}

My sequelize version is 2.0.2.

@epsyan Thanks. I have seen that workaround. I expect the Sequelize to be fixed internally, otherwise I would have to use the hook in every schema that is not efficient.

[Edit]
Just tried that workaround is not working in 2.0.2.

Issue is still open so it's not solved yet.

@thanpolas you initially refactored allowNull to be a schema valdiator, what is your opinion about customizable error messages and allow null?

@mickhansen Your link in the comment is broken.

@mickhansen Yes, thanks. I in fact don't like all of the validation error messages of Sequelize as they all are not user-friendly. If we could re-define custom messages for all validators in one place, it will be great.

@mickhansen, +1

@cithukyaw proposals and PR's always welcome :)

@mickhansen difficult to find a spare time to contribute this. wonder why those messages were initially implemented like system errors.
For example, Validation isNumeric failed should be The field must be numeric.

@cithukyaw we all have limited spare time. If you read the entire issue and the original PR change you can find the reasons, mostly it's to distinguish between schema validation and user validation.

@cithukyaw The error messages are directed at the programmer, not necesarily at the end user

@janmeier Those messages are related to the user inputs, so they are directly related to the end user. They should be returned to the end user for me. So, why we need to re-define all of them as user messages.

Programmer-related messages are handled with Error object.

@cithukyaw The field is numeric would be bad for user experience aswell. Not sure it's possible to implement something as domain driven and specific to UX as valdiations as generic error messages.

@cithukyaw You seem to have very strong feelings about what "should be done for you", so it's really an oppurtune time for you to come up with tangible proposal and changes :)

The Sequelize team has limited resources, and we currently have higher priorities. We will get to this eventually but it can easily be solved in the implementation layer and there's a difference of opinion whether or not stuff like this should be communicated directly to the end-user (i wouldn't). And i don't think generic error messages would ever satisfy the end user in terms of good UX.

@mickhansen

The field is numeric would be bad for user experience aswell. Not sure it's possible to implement something as domain driven and specific to UX as valdiations as generic error messages.

Yes, it is just for example. Such Validation isNumeric failed message is not ideal for the end user I think.

And that's exactly what the validations are - sub-types of Error ;)

I see your point, that it would be nice, but look at it this way. Right now we have one message for all errors: name of validator + 'failed'. If we were to do something like you said it would required a tailored error message for each validtor - someone would have to write and maintain those and they would bloat the core code. And as mick mentioned, most developers would override them anyways, to get validator error messages closer to their domain

Just a possibility by defining label in schema like

travelTime: {
    type: Sequelize.INTEGER,
    label: "Travel Time",
    allowNull: false,
    validate: {
        isNumeric: true
    }
}

or

travelTime: {
    type: Sequelize.INTEGER,
    label: "Travel Time",
    allowNull: false,
    validate: {
        isNumeric: { msg: "%s must be number." }
    }
}

Both could return "Travel time must be number". If label is not defined, just return "travelTime must be number", however, camelCase (travelTime in this case) could be converted to word-by-word (by Sequelize itself or by using another string manipulating dependency).

Does it make sense and is it possible?

@cithukyaw yeah that makes a lot of sense, likely possible, although a formalized API should probably be discussed. And then the work still needs to be done :)

Since the workaround is not working in 2.0.2, the following is my temporary workaround:

Use notEmpty: { msg: "xxxxx is missing" } in schema and set empty if null, undefined or 0.

params.travelTime = params.travelTime || "";
params.travelCost = params.travelCost || "";

Model.create(params).then(function() {
});

However, validation failed for the input 0. If you want to by-pass 0, you may need to check it explicitly or use the other validator such as is.

@cithukyaw i wasn't aware that that was _the workaround_ ;)
Have you tried using hooks?

My workaround right now is

        lastname: {
            type: DataTypes.STRING,
            defaultValue: '',
            validate: {
                notEmpty: { msg: 'Last Name is required' }
            }
        }

So what's the right way to provide a message for allowNull:false? Looks like once you put allowNull:false it is going to generate a cannot be null statement, how can you change this message?

@mshahriarinia It's not possible to change the messages for schema validations, you'll have to use a custom validator at the moment i'm afraid.

@alexcheuk nice! thanks for the idea :)

@alexcheuk seconded, thanks for pointing out this option.

@alexcheuk Also using this, thanks

Proper way to set allowNull messages

{
  email: {
    type: Sequelize.STRING,
    allowNull: false,
    validate: {
      notNull: {
        msg: 'Please enter your e-mail',
      }
    },
  },
}

Fixed in https://github.com/sequelize/sequelize/pull/6943 (v4)

@sushantdhiman I think we have a problem with this. The notNull validator was depreciate. So, when I try configure the code in the way you did, I get this error:

'Warning "notNull" validation has been deprecated in favor of Schema based "allowNull"'

make sense?

With master @diego-oliveria ?

No @samkelleher, it was on a stable version. I just tested in the master branch and it is working. My bad. 👍

@samkelleher I just realize that even in master this message shows up. Just need send the field with value and the message appears. I saw that in master, file validator-extras.js, that we have this piece of code:
`
// Deprecate this.
validator.notNull = function() {
throw new Error('Warning "notNull" validation has been deprecated in favor of Schema based "allowNull"');
};

In some situations this function is been called and cause this.

`

Why was this issue is closed? It's important to be able to customize messages for required fields missing and also handle cases where the attribute can be null but only under certain conditions.

Currently I'm using this dreadful hack in a few dozen places:

changeAt: {
  type: DataTypes.DATE,
  defaultValue: '',
  validate: {
    notEmpty: {
      msg: 'Change At is required.'
    }
  }
}

I would expected this to work:

changeAt: {
  type: DataTypes.DATE,
  validate: {
    required: function(value, next) {
      if (value) {
        return next();
      }
      return next('Change At is required.');
    },
    otherCustomValidation: ...
  }
}

But when the value is null or undefined, validation is entirely skipped, whether or not allowNull is set to true. Seems wrong. What if I want to allow null but only under some certain other conditions. I guess the only way to do that is using the ugly hack of setting the default value to empty string.

UPDATE: After more investigation, the hack I'm using actually works only if the attribute is undefined. It seems there is no way customize validation behavior (message or other conditions) if the attribute is null.

Can we reopen this?
As of 4.2.0, @sushantdhiman 's solution does not work.

      firstName: {
        type: Sequelize.STRING,
        allowNull: false,
        validate: {
          notNull: { msg: 'null is not valid' },
        },
      },

leads to

Validation error: Warning "notNull" validation has been deprecated in favor of Schema based "allowNull"
    at Promise.all.then (/.../sequelize/lib/instance-validator.js:77:15)

if firstName value is not null.

Getting this error

{
 "message": 'Warning "notNull" validation has been deprecated in favor of Schema based "allowNull"',
}

So what's the proper way to set custom message on notNull ?

It looks like there's isn't a way at the moment, possibly an oversight of deprecating notNull?

https://github.com/sequelize/sequelize/blob/d00f75df89a2e94178740d7893ce2418e0db5f61/lib/instance-validator.js#L325-L327

The fix we are using replaces the notNull function in validator-extras with,
validator.notNull = function(item){ return !validator.isNull(item); };

Any official update on this? This issue should not be closed.

Any solutions? As I see there is no capability to add not null error message now 😞

How does an ORM have a 3+ year old issue for customizing the validation error message when a required field is missing? This shouldn't be labeled as a feature request...

Building off what @boulosda provided above, you can monkeypatch this from the bottom of models/index.js 😭

/**
 * Monkey patch issue causing deprecation warning when customizing allowNull validation error
 *
 * See https://github.com/sequelize/sequelize/issues/1500
 */
Sequelize.Validator.notNull = function (item) {
    return !this.isNull(item);
};

+1

👍

+1

Thanks @timscott. The workaround worked as expected:

    name: {
        type: Sequelize.STRING(50),
        allowNull: false,
        defaultValue: '',
        validate: {
            notEmpty: {
                msg: 'The name is required.'
            }
        }
    }

+1

Is there any update on it?

 username: {
      type: STRING(32), allowNull: false, unique: true,
      validate: {
        notNull: { args: true, msg: "用户名不能为空" },
      }
    },

{
"message": "Warning \"notNull\" validation has been deprecated in favor of Schema based \"allowNull\""
}

@acodercat only 5.0.0-beta.9 or above

@acodercat only 5.0.0-beta.9 or above

How should I modify allowNull validate msg now?

@acodercat Not possible in v4, there are some hacks discussed in this thread though

So any workaround to set custom validate error message when it's null? The @timscott solution didn't work for me

@PauloLira this has already been implemented, you need to use >=5.0.0-beta.9 for the deprecated message to go away. See this comment above.

var User = sequelize.define('User', {
    email: {
      type: DataTypes.STRING,
      unique: true,
      allowNull: { args: false, msg: 'Email is required.' }, // not work
      validate: { isEmail: { msg: 'Invalid email.' } },
    },

// modify
email:{
  type:Data.Types.STRING,
 unique:true,
 allowNull:false,
 validate:{
   notNull:{
      msg:'this is custom allowNull error message'
   }
 }
}

@cjroth
You can use validate with isNull. if value is null, you can throw an error with custom message like bellow. (allowNull must be true)
input

Then your output will be appear like this .

output

Was this page helpful?
0 / 5 - 0 ratings