Joi: Joi v16: TypeError issue with valid(Joi.ref(x)).error()

Created on 25 Sep 2019  路  9Comments  路  Source: sideway/joi

Context

  • node version:10.16.3
  • joi version:16.1.4
  • environment (node, browser):node
  • used with (hapi, standalone, ...):hapi/standalone
  • any other relevant information:

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

Trying to validate two fields, making sure they are the same. Use case: password + re_password fields. This worked on Joi v15 but doesn't appear to work with Joi v16.

const schema = Joi.object().keys({
          key_first: Joi.string().required(),
          key_second: Joi.string().required().valid(Joi.ref('key_first')).error(() => 'key_second must match key_first'),
        })
schema.validate({
          key_first: 'something',
          key_second: 'something else',
        }, {abortEarly: false})

Seems to work if I remove the error() call. The problem is item.path is undefined, and it throws an exception.

Which result you had ?

Debug: internal, implementation, error 
    TypeError: Cannot read property 'filter' of undefined
    at Object.exports.details (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/errors.js:227:29)
    at Object.exports.process (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/errors.js:177:52)
    at Object.internals.entry (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/validator.js:139:26)
    at Object.exports.entry (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/validator.js:25:30)
    at internals.Base.validate (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/base.js:531:26)
    at handler (/home/miroslav/Projects/joitest/server.js:18:12)
    at module.exports.internals.Manager.execute (/home/miroslav/Projects/joitest/node_modules/@hapi/hapi/lib/toolkit.js:41:33)
    at Object.internals.handler (/home/miroslav/Projects/joitest/node_modules/@hapi/hapi/lib/handler.js:46:48)
    at exports.execute (/home/miroslav/Projects/joitest/node_modules/@hapi/hapi/lib/handler.js:31:36)
    at Request._lifecycle (/home/miroslav/Projects/joitest/node_modules/@hapi/hapi/lib/request.js:312:68)
Debug: internal, implementation, error 
    TypeError: Cannot read property 'filter' of undefined
    at Object.exports.details (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/errors.js:227:29)
    at Object.exports.process (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/errors.js:177:52)
    at Object.internals.entry (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/validator.js:139:26)
    at Object.exports.entry (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/validator.js:25:30)
    at internals.Base.validate (/home/miroslav/Projects/joitest/node_modules/@hapi/joi/lib/base.js:531:26)
    at handler (/home/miroslav/Projects/joitest/server.js:18:12)
    at module.exports.internals.Manager.execute (/home/miroslav/Projects/joitest/node_modules/@hapi/hapi/lib/toolkit.js:41:33)
    at Object.internals.handler (/home/miroslav/Projects/joitest/node_modules/@hapi/hapi/lib/handler.js:46:48)
    at exports.execute (/home/miroslav/Projects/joitest/node_modules/@hapi/hapi/lib/handler.js:31:36)
    at Request._lifecycle (/home/miroslav/Projects/joitest/node_modules/@hapi/hapi/lib/request.js:312:68)

What did you expect ?

{
  value: {...}
  error: {...}
}
bug

Most helpful comment

Well, you are using it wrong.

If you want to override the message, you should use .message(), .messages(), or .prefs({ messages }).

.error() is specifically designed to override the joi error and return the exact object you are providing.

All 9 comments

const schema = Joi.object().keys({
          key_first: Joi.string().required(),
          key_second: Joi.string().required().valid(Joi.ref('key_first'))**_.error(new Error( 'key_second must match key_first'))_**,   
        })
schema.validate({
          key_first: 'something',
          key_second: 'something else',
        }, {abortEarly: false})

===> when using Error Instance - Joi NOT returning any errors

error() requires an Error object. I fixed it so that it is better communicated now.

There's a related problem that error doesn't return any error, period. If I change the above example to:
.error(() => new Error('key_second must match key_first'))
Then there's no error.
Same with: .error(new Error('key_second must match key_first'))

@hueniverse What do you think? Should we reopen this or create new issue?

Seems to work fine for me:

> const Joi = require('.');
> const schema = Joi.object().keys({
...           key_first: Joi.string().required(),
...           key_second: Joi.string().required().valid(Joi.ref('key_first')).error(new Error( 'key_second must match key_first')),
...         })

> schema.validate({
...           key_first: 'something',
...           key_second: 'something else',
...         }, {abortEarly: false})
{ value: { key_first: 'something', key_second: 'something else' },
  error:
   Error: key_second must match key_first
       at repl:3:81
       at Script.runInThisContext (vm.js:122:20)
       at REPLServer.defaultEval (repl.js:332:29)
       at bound (domain.js:402:14)
       at REPLServer.runBound [as eval] (domain.js:415:12)
       at REPLServer.onLine (repl.js:642:10)
       at REPLServer.emit (events.js:203:15)
       at REPLServer.EventEmitter.emit (domain.js:448:20)
       at REPLServer.Interface._onLine (readline.js:308:10)
       at REPLServer.Interface._line (readline.js:656:8) }

And

> const Joi = require('.');

> const schema = Joi.object().keys({
...           key_first: Joi.string().required(),
...           key_second: Joi.string().required().valid(Joi.ref('key_first')).error(()=>new Error( 'key_second must match key_first')),
...         })

> schema.validate({
...           key_first: 'something',
...           key_second: 'something else',
...         }, {abortEarly: false})
{ value: { key_first: 'something', key_second: 'something else' },
  error:
   Error: key_second must match key_first
       at Object.Joi.object.keys.key_second.Joi.string.required.valid.error (repl:3:85)
       at Object.internals.finalize (/home/eran/code/hapijs/joi/lib/validator.js:460:36)
       at Object.exports.validate (/home/eran/code/hapijs/joi/lib/validator.js:335:26)
       at internals.Base.$_validate (/home/eran/code/hapijs/joi/lib/base.js:747:26)
       at Object.validate (/home/eran/code/hapijs/joi/lib/types/keys.js:107:45)
       at Object.exports.validate (/home/eran/code/hapijs/joi/lib/validator.js:313:26)
       at Object.internals.entry (/home/eran/code/hapijs/joi/lib/validator.js:131:28)
       at Object.exports.entry (/home/eran/code/hapijs/joi/lib/validator.js:25:30)
       at internals.Base.validate (/home/eran/code/hapijs/joi/lib/base.js:531:26)
       at repl:1:8 }

I think the problem is it鈥檚 Error object rather then the object that was returned before. So it can鈥檛 be Json encoded. I return this to a client via my api and I was using error() to tweak the message

Well, you are using it wrong.

If you want to override the message, you should use .message(), .messages(), or .prefs({ messages }).

.error() is specifically designed to override the joi error and return the exact object you are providing.

Ok thanks. Looking forward to using this new version now that I understand why I have these regressions

message() didn't work because any.valid doesn't support rules.
messages() worked:

Joi.string().required().valid(Joi.ref('key_first')).messages({'any.only': 'key_second must match key_first'})

Docs are a bit sketchy on those.

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

normancarcamo picture normancarcamo  路  3Comments

Taxi4you picture Taxi4you  路  3Comments

PaunPrashant picture PaunPrashant  路  3Comments

alekbarszczewski picture alekbarszczewski  路  3Comments

jamesdixon picture jamesdixon  路  4Comments