Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

joi errors not overriding for nested objects #1528

Closed
overflowz opened this issue Jun 15, 2018 · 7 comments
Closed

joi errors not overriding for nested objects #1528

overflowz opened this issue Jun 15, 2018 · 7 comments
Assignees
Labels
support Questions, discussions, and general support
Milestone

Comments

@overflowz
Copy link

Context

  • node version: 8.x
  • joi version: latest
  • environment (node, browser): node
  • used with (hapi, standalone, ...): standalone

What are you trying to achieve or the steps to reproduce ?

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')),
});

Which result you had ?

it returns 'city is required' unless all the nested objects are valid.

What did you expect ?

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'
@Marsup Marsup self-assigned this Jun 15, 2018
@Marsup
Copy link
Collaborator

Marsup commented Jun 15, 2018

Duplicate of #1219. I know it's confusing but it's documented.

@Marsup Marsup added the support Questions, discussions, and general support label Jun 15, 2018
@overflowz
Copy link
Author

overflowz commented Jun 15, 2018

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`

@overflowz
Copy link
Author

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.

@Marsup
Copy link
Collaborator

Marsup commented Jun 17, 2018

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;
    })
});

@overflowz
Copy link
Author

Ahh.. Now it's all clear. Thank you!

Closing this.

@Marsup Marsup added this to the 14.2.0 milestone Nov 25, 2018
Marsup added a commit that referenced this issue Nov 25, 2018
@Marsup
Copy link
Collaborator

Marsup commented Nov 25, 2018

Added a new syntax in 14.2.0 to support that more easily if you're interested.

@richarepo
Copy link

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?

@lock lock bot locked as resolved and limited conversation to collaborators Jun 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
support Questions, discussions, and general support
Projects
None yet
Development

No branches or pull requests

3 participants