Hi team, really appreciate the effort that has been into this validator to make it so dynamic and easy to use.
I'm using 16.1.4 version of the validator.
The problem I'm facing is with custom error messages. I've gone through https://github.com/hapijs/joi/issues/1739, and that did not help (in the sense that it does not accomplish the functionality for multiple keys).
My schema is:
const joiSchema = Joi.object({
a: Joi.string()
.error(new Error('a should be a type of text'))
.min(2)
.error(new Error('a should be a min of 2'))
.max(10)
.required(),
b: Joi.string()
.error(new Error(`b should be a type of text`))
.valid('INBOUND', 'OUTBOUND')
.error(new Error(`Incorrect input provided for field: b`))
.min(1)
.error(new Error(`b should at least have a length of 1`))
.max(100)
.required()
});
My validation code is: joiSchema.validate(payload, { abortEarly: false });
and my input payload is:
{
"a": 1,
"b": 2
}
Expected result:
{ message: "a should be a type of text, b should be a type of text" }
Actual result:
{ message: "a should be a min of 2" }
There are 3 concerns here:
abortEarly is set to false, the validation should proceed and additionally provide the error for 'b'. And similar to 'a', it should show at least the first encountered error, or all the errors encountered.I did a little test, and found out that if I use the custom error feature (any.error), even once anywhere, then it breaks the functionality.
By functionality I mean that:
abortEarly: false is ignored. Other schema keys are not validated..required should trigger (which is not happening) and the error message should be '\"a\" is required.' (since this is the joi-defined error for any.required).and by even once I mean:
const joiSchema = Joi.object({
a: Joi.string()
.error(new Error('a should be a type of text'))
.min(2)
.max(10)
.required(),
b: Joi.string()
.valid('INBOUND', 'OUTBOUND')
.min(1)
.max(100)
.required()
});
In this changed schema, the custom error is used only once.
I'm not sure yet, but I can look around the code if required.
Yes (but it might take some time, as I've barely gone through the code yet).
what version of @hapi/joi are you using ?
I'm using 16.1.4 it gives NO Errors ; below is the output
{
"value": {
"a": 1,
"b": 2
},
"error": {}
}
Sorry forgot to mention that. I'm also using the same 16.1.4. (I've updated the ticket with a little more details)
You are using the wrong method. .error() is not meant to override error messages. I've updated the documentation.
@hueniverse trying to use .message() however getting an error:
Error: Cannot apply rules to empty ruleset or the last rule added does not support rule properties
at new module.exports (/Users/daniels/sources/wix-node-platform/node_modules/@hapi/hoek/lib/error.js:21:15)
at module.exports (/Users/daniels/sources/wix-node-platform/node_modules/@hapi/hoek/lib/assert.js:20:11)
this is my validation code:
result.valid(...LANGUAGE_CODES).message({'any.only': 'invalid language'})
UPD: found how to tackle it with .prefs(...) looking into tests.
IMHO documentation should mention that for .valid and other non-ruleset based
@hueniverse Thanks.
@hugebdu I tried this:
const joiSchema = Joi.object({
a: Joi.string()
.messages({ 'any.only': `a should be a type of 'text'` })
.min(2)
.max(10)
.required(),
b: Joi.string()
.messages({ 'any.only': `b should be a type of 'text'` })
.valid('I', 'O')
.messages({ 'any.only': `b could either be 'I' or 'O'` })
.min(1)
.max(100)
.required()
});
with input as:
{
a: 1,
b: 2
}
Expected output: "a should be a type of 'text'. b should be a type of 'text'"
Actual output: "\"a\" must be a string. \"b\" must be one of [I, O]. \"b\" must be a string"
Can you please tell me what I'm doing wrong? (I went through the documentation: https://hapi.dev/family/joi/?v=16.1.5#anymessagesmessages, but could not find what is the correct usage)
Additional details:
After looking at tests and some code, I've tried:
Joi.string()
.prefs({
messages: {
english: { 'any.type': `a should be a type of 'text'` }
}
})
and
Joi.string()
.prefs({
messages: {
root: `a should be a type of 'text'`
}
})
But they all seem to fail to respond with custom message.
Update:
Ok, so after going through more code/documentation and tests/examples, I figured that out.
The correct schema to do this is:
Joi.string()
.min(2)
.max(10)
.required()
.messages({
'string.base': `"a" should be a type of 'text'`,
'string.empty': `"a" cannot be an empty field`,
'any.required': `"a" is a required field`
}),
You can have the .messages() at any level (as it is any.messages()). My preference is to keep it all together. The only pain is to find the keys for messages, i.e., in this example, 'string.base', 'string.empty', 'any.required' etc. I'm sure there must be a repo for all of these, but my current approach was to let my validation fail and find what error is returned. In the error object, the type is specified for the failure, then use that type in schema (under messages).
For not having to hard-code values, like in min/max, you can also use references:
'string.min': `"a" should have a minimum length of {#limit}`
Output: "\"a\" should have a minimum length of 2."
Thanks @hueniverse and @hugebdu.
The documentation is pretty detailed about which error codes go with which method.
Yes @hueniverse. I found the list of errors (along with description) here: https://github.com/hapijs/joi/blob/master/API.md#list-of-errors. Thanks again.
This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.
Most helpful comment
Yes @hueniverse. I found the list of errors (along with description) here: https://github.com/hapijs/joi/blob/master/API.md#list-of-errors. Thanks again.