Ajv: Duplicate `$id`s within the same document passes schema validation...

Created on 7 Nov 2020  路  6Comments  路  Source: ajv-validator/ajv

hey there :wave:

i'm guessing i'm missing something 馃 - the docs say:

You cannot have the same $id (or the schema identifier) used for more than one schema - the exception will be thrown

(source)

...but assigning the same $id to different schemas (within the same document) passes schema validation.

What version of Ajv are you using? Does the issue happen if you use the latest version?

v6.12.6, yes

Ajv options object

{
    allErrors: true,
    useDefaults: true,
    extendRefs: 'fail',
    missingRefs: 'fail',
    strictNumbers: true,
    strictDefaults: true,
    strictKeywords: true,
    unknownFormats: true,
    validateSchema: true,
    removeAdditional: 'all'
}

JSON Schema

{
    "$schema": "https://particle.io/draft-07/schema#",
    "$id": "http://example.com/example.json",
    "type": "object",
    "title": "Fake Custom Schema",
    "description": "A customized JSON schema for testing",
    "properties": {
        "foo": {
            "$id": "#/nope",
            "type": "integer"
        },
        "bar": {
            "$id": "#/nope",
            "type": "string"
        }
    }
}

Sample data

{
    "foo": 1,
    "bar": "ok"
}

Your code

const ajv = new AJV({
    allErrors: true,
    useDefaults: true,
    extendRefs: 'fail',
    missingRefs: 'fail',
    strictNumbers: true,
    strictDefaults: true,
    strictKeywords: true,
    unknownFormats: true,
    validateSchema: true
});

if (!ajv.validateSchema(schema)){
    throw new Error('Invalid schema!');
}

What results did you expect?

i expected my schema to be considered invalid and an error to be throw - Error: Invalid schema!

limitation

Most helpful comment

Let鈥檚 keep it open. I鈥檝e only added a failed test for it, it would be good to resolve.

All 6 comments

validateSchema will not catch issues like that, as it only validates structure and syntax (by validating it against meta-schema as JSON document), but it does not do semantic validation - unknown keywords or formats, missing refs, or duplicate IDs. To catch issues like that you need to compile.

The current example though goes past the compile as well - it is not a common way to write schemas.

A more common approach would be to have definitions (or $defs in the next version of the spec) and only reference subschemas from there:

{
  $id: "http://example.com/example.json",
  $defs: {
    foo: {
      $id: "#/nope",
      type: "integer",
    },
    bar: {
      $id: "#/nope",
      type: "string",
    },
  },
  type: "object",
  properties: {
    foo: {$ref: "#/foo"},
    bar: {$ref: "#/bar"},
  },
}

That schema throws error when compiled.

The issue won't be addressed in v6, but is likely to be addressed in v7.

ah, ok. thanks 馃檹馃憤

Let鈥檚 keep it open. I鈥檝e only added a failed test for it, it would be good to resolve.

using your example, i get an error (Schema http://example.com/example.json is loaded but http://example.com/example.json#/foo cannot be resolved) but changing every $id and $ref to "#/nope", i still don't get an error about duplication of $ids

```javascript
const ajv = new AJV({
allErrors: true,
useDefaults: true,
extendRefs: 'fail',
missingRefs: 'fail',
strictNumbers: true,
strictDefaults: true,
strictKeywords: true,
unknownFormats: true,
validateSchema: true
});

try {
ajv.compile({
$id: "http://example.com/example.json",
$defs: {
foo: {
$id: "#/nope",
type: "integer",
},
bar: {
$id: "#/nope",
type: "string",
},
},
type: "object",
properties: {
foo: {$ref: "#/nope"},
bar: {$ref: "#/nope"},
},
});
} catch (error){
console.log(error);
}

I see - it was failing because refs should have been #/$defs/foo and not because of duplication

fix merged to v7-beta

Was this page helpful?
0 / 5 - 0 ratings