joi
joi copied to clipboard
Custom error is ignored with multiply array items
Support plan
- is this issue currently blocking your project? (yes/no): yes
- is this issue affecting a production system? (yes/no): no
Context
- node version: 14.19.0
- module version with issue: 17.9.1, 17.9.2
- last module version without issue:
- environment (e.g. node, browser, native): node
- used with (e.g. hapi application, another framework, standalone, ...):
- any other relevant information:
What are you trying to achieve or the steps to reproduce?
Schema:
Joi.object({
test: Joi.array().items(
Joi.string(),
Joi.number()
.custom(function(value, helpers){
if (value===5)
return helpers.error('test_error');
return value;
})
.messages({
'test_error': 'Test error message',
})
).single(),
})
Data To Validate:
{
test: 5,
}
What was the result you got?
Validation Error: "test" does not match any of the allowed types
What result did you expect?
Validation Error: Test error message
This is interesting. If you remove Joi.string()
, you get the result you're looking for.
Joi.object({
test: Joi.array()
.items(
Joi.number() //Removed Joi.string()
.custom(function (value, helpers) {
if (value === 5) return helpers.error('test_error');
return value;
})
.messages({
test_error: 'Test error message',
}),
)
.single(),
});
//Returns 'Test error message'
If you instead return 6
instead of helpers.error('test_error')
, it replaces it with 6
and passes validation.
Joi.object({
test: Joi.array()
.items(
Joi.string(),
Joi.number()
.custom(function (value, helpers) {
if (value === 5) return 6; //Replace error message with 6
return value;
})
.messages({
test_error: 'Test error message',
}),
)
.single(),
});
//Passes validation, converts {test: 5} to {test: [6]}
That's normal behavior, all possibilities will be attempted until a valid one is found, if none, there is no way to distinguish which one is the most likely, so this is the only rational error to provide.
@Marsup at least the second one has custom handler and it could have priority. Moreover I got the correct result by wrapping "items" to alternatives(). Why it's not a problem for alternatives() to distinguish it?
Joi.object({
test: Joi.array().items(Joi.alternatives(
Joi.string(),
Joi.number()
.custom(function(value, helpers){
if (value===5)
return helpers.error('test_error');
return value;
})
.messages({
'test_error': 'Test error message',
})
)).single(),
})