ajv-validator/ajv-errors

Extraneous error with an empty string is reported when `singleError` option is turned on

mati-o opened this issue · 2 comments

Package Versions:

Tested the following combinations:

  • ajv@7.0.3 with ajv-errors@2.0.0
  • ajv@6.12.6 with ajv-errors@1.0.1

Background

Good day, I have observed a strange behavior when using ajv-errors with singleError flag turned on. Honestly, I can't remember why even it was turned on in my code but when I turn it off, this unexpected behavior stops.

The code below is the minimum reproducible example for the issue I am describing. I had a fairly complex schema but I have simplified to the most basic example I could to illustrate the issue.

When I have two errorMessage properties, set as follows - one in the top level and the other in one of the fields, an extraneous empty error is reported.

(In my case there were a lot more).

I hope you'd shed some light on this unexpected behavior. Many thanks!

Code

const AJV = require('ajv').default;
const ajvErrors = require('ajv-errors');

const validator = new AJV({ allErrors: true});

// Add AJV errors with singleError: true
ajvErrors(validator, {
  singleError:true
});

validator.addSchema({
  $id: 'pizzaOrder',
  type:'object',
  additionalProperties: false,
  errorMessage:{
    additionalProperties:'Pizza order is invalid'
  },
  properties:{
    price:{
      type:'number'
    },
    toppings:{
      type:'object',
      additionalProperties: false,
      errorMessage: {
        _: 'Unsupported topping'
      },
      properties: {
        pineapple:{
          type: 'boolean'
        }
      }
    }
  }
});

validator.validate('pizzaOrder', { 
  somethingBad: true, 
  toppings:{
    pineapple:true
  }
});

console.log(JSON.stringify(validator.errors, null, 2));;

Expected Result:

Since I have deliberately put an additionalProperty called somethingBad I would expect it to be reported as follows:

[
  {
    "keyword": "errorMessage",
    "dataPath": "",
    "schemaPath": "#/errorMessage",
    "params": {
      "errors": [
        {
          "keyword": "additionalProperties",
          "dataPath": "",
          "schemaPath": "#/additionalProperties",
          "params": {
            "additionalProperty": "somethingBad"
          },
          "message": "should NOT have additional properties",
          "emUsed": true
        }
      ]
    },
    "message": "Pizza order is invalid"
  }
]

Actual Result:

But actually, as highlighted below, there's an extra error that creeps in with an empty message and empty params.errors for toppings which actually is totally valid.

[
+  {
+   "keyword": "errorMessage",
+    "dataPath": "/toppings",
+    "schemaPath": "#/properties/toppings/errorMessage",
+    "params": {
+      "errors": []
+    },
+    "message": ""
+  },
  {
    "keyword": "errorMessage",
    "dataPath": "",
    "schemaPath": "#/errorMessage",
    "params": {
      "errors": [
        {
          "keyword": "additionalProperties",
          "dataPath": "",
          "schemaPath": "#/additionalProperties",
          "params": {
            "additionalProperty": "somethingBad"
          },
          "message": "should NOT have additional properties",
          "emUsed": true
        }
      ]
    },
    "message": "Pizza order is invalid"
  }
]

Temporal Workarounds:

Currently I have turned of singleError completely, hopefully it won't affect my other schema's error reports

ajvErrors(validator, {
-   singleError:true // removed
});

Another thing I have noticed, which may aid finding the issue is that when I did changed the schema this way:

{
  $id: 'pizzaOrder',
  type:'object',
  additionalProperties: false,
  errorMessage:{
    additionalProperties:'Pizza order is invalid'
  },
  properties:{
    price:{
      type:'number'
    },
    toppings:{
      type:'object',
      additionalProperties: false,
-      errorMessage: {
-       _: 'Unsupported topping'
-      },
+     errorMessage: 'Unsupported topping'
      properties: {
        pineapple:{
          type: 'boolean'
        }
      }
    }
  }
}

The problem went away too. In my case it's not possible however, since I have other error keyword in my full example.

Let me know if any clarifications are required

Thank you. Am I right that this issue happens in both versions (Ajv v6 and v7), so it’s not a regression?

Yes indeed it happens in both 6 and 7 (with ajv-errors 1 and 2 respectively).