joi icon indicating copy to clipboard operation
joi copied to clipboard

`abortEarly: false` not honored with custom error message

Open the-noob opened this issue 3 years ago • 1 comments

Support plan

Community

  • is this issue currently blocking your project?: yes
  • is this issue affecting a production system?: yes

Context

  • 14.15.4:
  • 17.4:
  • 14:
  • node (e.g. node, browser, native):
  • standalone (e.g. hapi application, another framework, standalone, ...):

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

I'm trying to upgrade from Joi 14 to 17 and can't reproduce the same behaviour.

In 14 I had something like

export const errorA = "exists and min 2";
export const errorB = "exists and min 5";

export const schema = Joi.object({
  a: Joi.string()
    .required()
    .min(2)
    .error(() => ({
      message: errorA,
    })),
  b: Joi.string()
    .required()
    .min(5)
    .error(() => ({
      message: errorB,
    })),
});
const result = Joi.validate({}, schema, {  abortEarly: false,  allowUnknown: true });

 // result.error.details. would be an array with errorA/B messages

I'm trying to do the same with 17 only getting only the first error message ?

const schema = Joi.object({
  a: Joi.string()
    .required()
    .min(2)
    .error(() => new Error("exists and min 2")),
  b: Joi.string()
    .required()
    .min(5)
    .error(() => new Error("exists and min 5")),
});
const result = schema.validate({}, { abortEarly: false });

// result.error is a single Error("exists and min 2")) instance, not an array

I've seen the suggestions to use messages but I don't see how to return a single one, something like code: "any.all" This will return an array of details with the expected (custom) error message;

const schema = Joi.object({
  a: Joi.string()
    .required()
    .min(2)
    .messages({ "any.required": "required, min 2" }),
  b: Joi.string()
    .required()
    .min(5)
    .messages({ "any.required": "exists and min 5" }),
});
const result = schema.validate({}, { abortEarly: false });
console.debug(result.error.details);

[
  {
    message: 'required, min 2',
    path: [ 'a' ],
    type: 'any.required',
    context: { label: 'a', key: 'a' }
  },
  {
    message: 'exists and min 5',
    path: [ 'b' ],
    type: 'any.required',
    context: { label: 'b', key: 'b' }
  }
]

But if I validate a partially complete input I have to supply the custom message for every validator code in the chain

const schema = Joi.object({
  a: Joi.string()
    .required()
    .min(2)
    .messages({ "any.required": "required, min 2" }),
  b: Joi.string().required().min(5).messages({
    "any.required": "exists and min 5",
    "string.min": "exists and min 5",
  }),
});
const result = schema.validate({ b: "s" }, { abortEarly: false });

the-noob avatar Apr 14 '21 16:04 the-noob

This is also the case with external()

Sydney-o9 avatar Jul 23 '23 09:07 Sydney-o9