Joi: array().min() does not work in conjunction with .items()

Created on 3 Oct 2017  路  7Comments  路  Source: sideway/joi

Context

  • node version: v6.11.2
  • joi version: 11.1.1
  • environment node
  • used with standalone

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

Trying to ensure at least one item matching a joi object schema is contained in an array called tracks.

Schema:

const schema = {
    // some other fields go here
    tracks: Joi.array().min(1)
      .items(Joi.object({
        id: Joi.string().required(),
        name: Joi.string().required(),
        description: Joi.string()
      }))
      .required(),
  }

**Input:**
```js
const obj = {
    // some other fields go here
    tracks: [ { id: '84ece517-d116-47f8-9592-c5a919ce2d0f', name: 'asdfasdf' } ]
}

Validation call:

const joiOptions = {
      // the ember serializer sends the whole model,
      // so we ignore keys we don't handle,
      // but also remove them from the request.
      // This way, only validated parameters are
      // ever passed to the application.
      allowUnknown: true,
      stripUnknown: true,
    };
const result = Joi.validate(obj, schema, joiOptions);

Which result you had ?

The following error:

{ ValidationError: child "tracks" fails because ["tracks" must contain at least 1 items]
    at Object.exports.process (path/to/my/project/node_modules/joi/lib/errors.js:186:19)
    at _validateWithOptions (path/to/my/project/node_modules/joi/lib/types/any/index.js:663:31)
    at root.validate (path/to/my/project/node_modules/joi/lib/index.js:136:23)
    at module.exports (path/to/my/project/api/policies/requestParams.js:59:26)
    at routeTargetFnWrapper (path/to/my/project/node_modules/sails/lib/router/bind.js:181:5)
    at callbacks (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:164:37)
    at param (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:138:11)
    at pass (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:145:5)
    at nextRoute (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:100:7)
    at callbacks (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:167:11)
    at module.exports (path/to/my/project/api/policies/bodyJsonParser.js:22:3)
    at routeTargetFnWrapper (path/to/my/project/node_modules/sails/lib/router/bind.js:181:5)
    at callbacks (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:164:37)
    at param (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:138:11)
    at pass (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:145:5)
    at nextRoute (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:100:7)
    at callbacks (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:167:11)
    at module.exports (path/to/my/project/api/policies/authenticated.js:11:12)
    at routeTargetFnWrapper (path/to/my/project/node_modules/sails/lib/router/bind.js:181:5)
    at callbacks (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:164:37)
    at param (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:138:11)
    at pass (path/to/my/project/node_modules/@sailshq/express/lib/router/index.js:145:5)
  isJoi: true,
  name: 'ValidationError',
  details: 
   [ { message: '"tracks" must contain at least 1 items',
       path: [Object],
       type: 'array.min',
       context: [Object] } ],
  _object: 
   { // some other values go here
     tracks: [ [Object] ] },
  annotate: [Function] }

What did you expect ?

The validation succeeding.

Note: commenting out the .items() call makes the validation work as expected, however I'd like to validate the contents of the array together with the length.

It also seems like there is no unit test in the Joi library that tests the .min() function in conjunction with .items(), so that may have to be added as well.

non issue

Most helpful comment

In your case that's a misunderstanding of the stripUnknown option. See https://runkit.com/590207717e2df30012fa390b/59f8966c6d1095001217737d. (and I know, it's a weird default, someday I'll break that behavior)

All 7 comments

Sorry, can't reproduce locally.

@Marsup: Came here with the same problem and finally found that a bad key in the object was producing this error child "tracks" fails because ["tracks" must contain at least 1 items] which is misleading. See https://runkit.com/chris-verclytte/59f88d57ee1e3000127ef324 for live example. Maybe it could be improved with a message properly indicating that the nested object is incorrect ?

In your case that's a misunderstanding of the stripUnknown option. See https://runkit.com/590207717e2df30012fa390b/59f8966c6d1095001217737d. (and I know, it's a weird default, someday I'll break that behavior)

My bad, I had not seen this possible configuration of stripUnknown, thanks for the clarification !

https://github.com/hapijs/joi/blob/v13.1.2/API.md#validatevalue-schema-options-callback

- stripUnknown - remove unknown elements from objects and arrays. Defaults to false.
   when true, all unknown elements will be removed. 
   when an object :
      - arrays - set to true to remove unknown items from arrays.
      - objects - set to true to remove unknown keys from objects.

u'd better use

allowUnknown : true

or

stripUnknown: {
  objects: true,
},

because when use stripUnknown:true , this will delete the wrong object in array , when this has only one item , deleted it's 0 . so this error reject

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

alekbarszczewski picture alekbarszczewski  路  3Comments

chrisegner picture chrisegner  路  4Comments

sergibondarenko picture sergibondarenko  路  3Comments

PaunPrashant picture PaunPrashant  路  3Comments

kevbook picture kevbook  路  4Comments