const userSchema = Joi.object().keys({
city: Joi.object().keys({
id: Joi.number().required().error(new Error('invalid city id')),
}).required().error(new Error('city is required')),
});
it returns 'city is required' unless all the nested objects are valid.
display error for each part.
while this works without .error(), I want to be able to send custom error messages for each part.
For example:
const userSchema = Joi.object().keys({
city: Joi.object().keys({
id: Joi.number().required().error(new Error('invalid city id')),
}).required().error(new Error('city is required')),
});
userSchema.validate({ city: { id: 'asfasf' } }); // returns 'city is required', while I'm expecting it to return 'invalid city id'
Duplicate of https://github.com/hapijs/joi/issues/1219. I know it's confusing but it's documented.
Even applying abortEarly: false, it still does not override that error. What's the workaround on this?
code:
const Joi = require('joi');
const schema = Joi.object().keys({
city: Joi.object().keys({
id: Joi.number().required().error(new Error('invalid city')),
}).required().error(new Error('city is required'))
});
console.log(schema.validate({ city: { id: 'asd' } }, { abortEarly: true }).error); // returns `city is required` instead of `invalid city`
Seems no response so far, as a workaround, I wrote a helper function which gets labels instead and prints them (only first item in my case, no need multiple).
P.S using ramda & ramda-fantasy libraries.
const getProp = R.useWith(R.path, [R.split('.')]);
const maybeGetProp = R.curry((prop, obj) => F.Maybe(getProp(prop, obj)));
const maybeGetJoiError = R.pipeK(maybeGetProp('error.details'), x => F.Maybe(R.head(x)), maybeGetProp('context.key'));
const userSchema = joi.object().keys({
city: joi.object().keys({
id: joi.number().required().label('invalid city'),
}).required().label('city is required')
});
const res = userSchema.validate({ city: {} }, { abortEarly: false });
maybeGetJoiError(res); // returns Maybe.Just({ value: 'invalid city' }) or Maybe.Nothing().
Let me know if it's correct approach for labels (e.g parsing correctly).
Thanks.
I think you missed the complexity of error(), maybe the documentation is not enough there. You can see joi schemas as big nested try/catch blocks that can throw several types of errors. So in your original code, id was throwing 'invalid city id' because of type mismatch, it was then caught by city which turned it into 'city is required' without even considering what happened.
A working example would be:
const schema = Joi.object().keys({
city: Joi.object().keys({
id: Joi.number().required().error(new Error('invalid city')),
}).required().error((errors) => {
// If at least one error comes from city itself
if (errors.some(e => e.context.key === 'city')) {
return new Error('city is required');
}
return errors;
})
});
Ahh.. Now it's all clear. Thank you!
Closing this.
Added a new syntax in 14.2.0 to support that more easily if you're interested.
Added a new syntax in 14.2.0 to support that more easily if you're interested.
Can you provide a direct link to that new syntax?
Most helpful comment
Can you provide a direct link to that new syntax?