If you define a non-type schema object, Joi converts it internally to the object() . So this diagram:
var schema = { type: Joi.string().optional(), tags: Joi.string().optional() };
becomes:
var schema = Joi.object().keys({ type: Joi.string().optional(), tags: Joi.string().optional() });
Since you set the presence value to forbidden in the server settings, it applies to the type of the object, so the scheme becomes:
var schema = Joi.object().forbidden().keys({ type: Joi.string().optional(), tags: Joi.string().optional() });
As you can see, it designates the main object as forbidden, which will not allow any value other than undefined :
var Joi = require('joi'); var schema = Joi.object().forbidden().keys({ type: Joi.string().optional(), tags: Joi.string().optional() }); var value = {}; Joi.validate(value, schema, { presence: 'forbidden' }, function (err, value) { console.log(err); });
It outputs:
{ [ValidationError: value is not allowed] name: 'ValidationError', details: [ { message: 'value is not allowed', path: 'value', type: 'any.unknown' } ], _object: {}, annotate: [Function] }
So, you need to mark the main object either required or optional to override forbidden :
validate: { query: Joi.object().required().keys({ type: Joi.string().optional(), tags: Joi.string().optional() }) }