Joi: Valid and invalid at the same time when using default with required

Created on 26 Jan 2016  路  9Comments  路  Source: sideway/joi

I have a schema defined like this:

const schema = joi.object().keys({
  _id: Joi.string().guid().default(generateUUID, 'Random uuid v4.').required(),
  string: Joi.string(),
  // ... other keys here ...
}).options({
  abortEarly: false,
  convert: true,
  allowUnknown: true,
  stripUnknown: true,
  noDefaults: false,
});

If I run schema.validate({}) without passing _id I get an output value with the correct default value applied to _id but also an error != null where it complains about _id being required

{
    "error": {
        "isJoi": true,
        "name": "ValidationError",
        "details": [
            {
                "message": "\"_id\" is required",
                "path": "_id",
                "type": "any.required",

                "context": {
                    "key": "_id"
                }
            }
        ],
        "_object": {
            "string": "string value",
        }
    },
    "value": {
         "string": "string value",
        "_id": "091a7172-1cc5-4b00-ac6c-d1460d74c604"
    }
}

non issue

Most helpful comment

@Marsup I get the point about abortEarly but why:

You shouldn't mix required and default, it's contradictory.

If I don't supply a value it should get the default value, required is to make sure that I can't pass a value like null. After default is applied the schema has a value and so the required rule shouldn't fail

All 9 comments

More details, this seems to happen only when using an extended schema:

let baseSchema = Joi.object().options({
  abortEarly: false,
  convert: true,
  allowUnknown: true,
  stripUnknown: true,
  noDefaults: false,
});

let baseModel = baseSchema.keys({
  _id: Joi.string().guid().default(generateUUID, 'Random uuid v4.').required(),
});

let model = baseModel.keys({
  string: Joi.string(),
});

when validation model

Actually it happens also when not using an extended schema but in that case _id's default function is not applied at all

This is indeed the normal behavior with abortEarly false. You don't provide an id so required causes an error, then it goes on with the other rules, so default generate your uuid. You shouldn't mix required and default, it's contradictory.

@Marsup I get the point about abortEarly but why:

You shouldn't mix required and default, it's contradictory.

If I don't supply a value it should get the default value, required is to make sure that I can't pass a value like null. After default is applied the schema has a value and so the required rule shouldn't fail

null is denied by default. required is evaluated before default.

Thanks for clarification!
As a user of Joi I'd expect required() and default() to play nice together. But at least now I see how to override the behaviour to what I want. I'll use default() with optional() instead of required(), despite counter-intuitive (for me)

optional is the default, just don't put anything.

@Marsup you're right. But in my project required is default, hence the confusion.

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jamesdixon picture jamesdixon  路  4Comments

n-sviridenko picture n-sviridenko  路  3Comments

farwayer picture farwayer  路  3Comments

a-c-m picture a-c-m  路  3Comments

alekbarszczewski picture alekbarszczewski  路  3Comments