Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reference resolution issue in v7 #1414

Closed
solymosi opened this issue Jan 27, 2021 · 3 comments
Closed

Reference resolution issue in v7 #1414

solymosi opened this issue Jan 27, 2021 · 3 comments

Comments

@solymosi
Copy link

solymosi commented Jan 27, 2021

I'm using version 7.0.3.

Consider the following piece of code:

const Ajv = require("ajv").default;

const instance = new Ajv({
  loadSchema: uri => {
    return Promise.resolve({
      $id: "http://two/",
      type: "object",
      properties: {
        bar: {
          $ref: "#/definitions/bar",
        },
      },
      definitions: {
        bar: {
          type: "string",
        },
      },
    });
  },
});

instance.compileAsync(
  {
    $id: "http://one/",
    type: "object",
    properties: {
      foo: {
        $ref: "#/definitions/foo",
      },
    },
    definitions: {
      foo: {
        $ref: "http://two/",
      },
    },
  },
  false
);

For whatever reason when processing the lazy loaded schema http://two/ Ajv thinks that the base URL is still http://one/ and tries to resolve the bar property reference accordingly, resulting in this error:

Error: AnySchema http://one/ is loaded but http://one/#/definitions/bar cannot be resolved
    at Ajv.checkLoaded (D:\dev\cis-dm-core\node_modules\ajv\lib\core.ts:377:15)
    at Ajv._compileAsync (D:\dev\cis-dm-core\node_modules\ajv\lib\core.ts:369:21)
    at Ajv._compileAsync (D:\dev\cis-dm-core\node_modules\ajv\lib\core.ts:371:30)

This problem is new in version 7, it first popped up after upgrading from version 6.

I've spent several hours debugging this issue and it seems like that changing this line:
https://github.com/ajv-validator/ajv/blob/v7.0.3/lib/compile/index.ts#L265

if (id === normalizeId(ref)) return new SchemaEnv({schema: schOrRef.schema, root, baseId})

to

if (id === normalizeId(ref)) return new SchemaEnv({schema: schOrRef.schema, root, schOrRef.baseId})

solves the issue in this particular case. I don't have enough knowledge of the codebase to be able to tell if this is the proper fix though, i.e. whether it could break something else.

If #/definitions/foo is inlined:

instance.compileAsync(
  {
    $id: "http://one/",
    type: "object",
    properties: {
      foo: {
        $ref: "http://two/",
      },
    },
  },
  false
);

then everything works as expected.

@epoberezkin
Copy link
Member

is it specific to async loading, or it happened for schema added with addSchema as well?

@solymosi
Copy link
Author

@epoberezkin It is indeed also broken if I use addSchema, and even when using compile instead of compileAsync. Thus, it's purely a reference resolution issue, it likely has nothing to do with the way the schemas are loaded.

const Ajv = require("ajv").default;

const instance = new Ajv({
  loadSchema: () => undefined,
});

instance.addSchema({
  $id: "http://two/",
  title: "Properties",
  type: "object",
  properties: {
    bar: {
      $ref: "#/definitions/bar",
    },
  },
  definitions: {
    bar: {
      type: "string",
    },
  },
});

instance.compile(
  {
    $id: "http://one/",
    type: "object",
    properties: {
      foo: {
        $ref: "#/definitions/foo",
      },
    },
    definitions: {
      foo: {
        $ref: "http://two/",
      },
    },
  },
  false
);
Error: can't resolve reference #/definitions/bar from id http://one/#

@solymosi solymosi changed the title compileAsync base URL confusion with asynchronously loaded references in v7 Reference resolution issue in v7 Jan 29, 2021
@epoberezkin
Copy link
Member

@solymosi thank you

I can reproduce: https://runkit.com/esp/601700c43e06c0001a957eff

It indeed happens in v7 and not in v6 - good catch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants