{"action":"created","issue":{"url":"https://api.github.com/repos/epoberezkin/ajv/issues/801","repository_url":"https://api.github.com/repos/epoberezkin/ajv","labels_url":"https://api.github.com/repos/epoberezkin/ajv/issues/801/labels{/name}","comments_url":"https://api.github.com/repos/epoberezkin/ajv/issues/801/comments","events_url":"https://api.github.com/repos/epoberezkin/ajv/issues/801/events","html_url":"https://github.com/epoberezkin/ajv/issues/801","id":330299869,"node_id":"MDU6SXNzdWUzMzAyOTk4Njk=","number":801,"title":"\"Maximum call stack size exceeded\" when using compileAsync + circular references in some schemas","user":{"login":"Hirntoasted","id":1835569,"node_id":"MDQ6VXNlcjE4MzU1Njk=","avatar_url":"https://avatars1.githubusercontent.com/u/1835569?v=4","gravatar_id":"","url":"https://api.github.com/users/Hirntoasted","html_url":"https://github.com/Hirntoasted","followers_url":"https://api.github.com/users/Hirntoasted/followers","following_url":"https://api.github.com/users/Hirntoasted/following{/other_user}","gists_url":"https://api.github.com/users/Hirntoasted/gists{/gist_id}","starred_url":"https://api.github.com/users/Hirntoasted/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hirntoasted/subscriptions","organizations_url":"https://api.github.com/users/Hirntoasted/orgs","repos_url":"https://api.github.com/users/Hirntoasted/repos","events_url":"https://api.github.com/users/Hirntoasted/events{/privacy}","received_events_url":"https://api.github.com/users/Hirntoasted/received_events","type":"User","site_admin":false},"labels":[{"id":213637991,"node_id":"MDU6TGFiZWwyMTM2Mzc5OTE=","url":"https://api.github.com/repos/epoberezkin/ajv/labels/bug","name":"bug","color":"fc2929","default":true}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2018-06-07T14:32:04Z","updated_at":"2018-06-10T12:14:59Z","closed_at":"2018-06-10T10:44:06Z","author_association":"NONE","body":"Hi,\r\ni'm working on a project where we want to validate json data based using various schema files that are interconnected via $refs.\r\nMy plan was to use compileAsync on a starting schema and load the referenced schemas by implementing a loadSchema function. However i run into `Maximum call stack size exceeded` errors when i execute the validation function.\r\nBelow is a (hopefully) minimal example of the schema structure causing the error (see _Your code_ for the full example) .\r\nSome additional notes about this:\r\n\r\n- i also tried manually loading the additional schemas (see `validate()` in the code example below) which seems to work, the error occured for me only when using compileAsync (see `validateAsync()`) \r\n- the schemas `foo` and `bar` form a circular reference\r\n- for some reason, the reference to the seemingly unrelated `other` schema needs to be there to cause the error. Therefore i suspect that the circular reference itself is not the root cause\r\n- The `other` reference can also be moved to the `bar` schema for similar result\r\n\r\n**What version of Ajv are you using? Does the issue happen if you use the latest version?**\r\n6.5.0, yes\r\n\r\n\r\n**Ajv options object**\r\n\r\n\r\n```javascript\r\n{\r\n    loadSchema: (uri) => {\r\n      switch(uri) {\r\n        case 'foo':\r\n          return Promise.resolve(fooSchema);\r\n        case 'bar':\r\n          return Promise.resolve(barSchema);\r\n        case 'other':\r\n          return Promise.resolve(otherSchema);\r\n      }\r\n    }\r\n  }\r\n```\r\n\r\n\r\n**JSON Schema**\r\n\r\n```json\r\nconst fooSchema = {\r\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n  \"$id\": \"foo\",\r\n  \"type\": \"object\",\r\n  \"properties\": {\r\n    \"bar\": {\r\n      \"$ref\": \"bar\"\r\n    },\r\n    \"other\": {\r\n      \"$ref\": \"other\"\r\n    }\r\n  }\r\n};\r\n\r\nconst barSchema = {\r\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n  \"$id\": \"bar\",\r\n  \"type\": \"object\",\r\n  \"properties\": {\r\n    \"foo\": {\r\n      \"$ref\": \"foo\"\r\n    }\r\n  }\r\n};\r\n\r\nconst otherSchema = {\r\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n  \"$id\": \"other\"\r\n};\r\n\r\nconst schema = {\r\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n  \"$id\": \"list\",\r\n  \"type\": \"object\",\r\n  \"properties\": {\r\n    \"foo\": {\r\n      \"$ref\": \"foo\"\r\n    }\r\n  }\r\n};\r\n\r\n```\r\n\r\n\r\n**Sample data**\r\n\r\n```json\r\n{\r\n  \"foo\": {}\r\n};\r\n\r\n```\r\n\r\n\r\n**Your code**\r\n\r\n```javascript\r\nconst ajv = require('ajv');\r\n\r\nconst fooSchema = {\r\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n  \"$id\": \"foo\",\r\n  \"type\": \"object\",\r\n  \"properties\": {\r\n    \"bar\": {\r\n      \"$ref\": \"bar\"\r\n    },\r\n    \"other\": {\r\n      \"$ref\": \"other\"\r\n    }\r\n  }\r\n};\r\n\r\nconst barSchema = {\r\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n  \"$id\": \"bar\",\r\n  \"type\": \"object\",\r\n  \"properties\": {\r\n    \"foo\": {\r\n      \"$ref\": \"foo\"\r\n    }\r\n  }\r\n};\r\n\r\nconst otherSchema = {\r\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n  \"$id\": \"other\"\r\n};\r\n\r\nconst schema = {\r\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\r\n  \"$id\": \"list\",\r\n  \"type\": \"object\",\r\n  \"properties\": {\r\n    \"foo\": {\r\n      \"$ref\": \"foo\"\r\n    }\r\n  }\r\n};\r\n\r\nconst data = {\r\n  \"foo\": {}\r\n};\r\n\r\nfunction validate() {\r\n  const validator = new ajv();\r\n\r\n  validator.addSchema(fooSchema);\r\n  validator.addSchema(barSchema);\r\n  validator.addSchema(otherSchema);\r\n\r\n  const validate = validator.compile(schema);\r\n  console.log('sync', validate(data));\r\n}\r\n\r\nasync function validateAsync() {\r\n  const validator = new ajv({\r\n    loadSchema: (uri) => {\r\n      switch(uri) {\r\n        case 'foo':\r\n          return Promise.resolve(fooSchema);\r\n        case 'bar':\r\n          return Promise.resolve(barSchema);\r\n        case 'other':\r\n          return Promise.resolve(otherSchema);\r\n      }\r\n    }\r\n  });\r\n\r\n  try {\r\n    const validate = await validator.compileAsync(schema);\r\n    console.log('async', validate(data));\r\n  } catch(error) {\r\n    console.error('async', error);\r\n  }\r\n}\r\n\r\nvalidate();\r\nvalidateAsync();\r\n```\r\n\r\n\r\n**Validation result, data AFTER validation, error messages**\r\n\r\n```\r\nsync true\r\nasync RangeError: Maximum call stack size exceeded\r\n    at callValidate (.../ajv/lib/ajv.js:1:1)\r\n    at callValidate (.../ajv/lib/ajv.js:370:28)\r\n    ...\r\n```\r\n\r\n**What results did you expect?**\r\ncompile() and compileAsync() should provide the same result - no `call stack exceeded` error should occure\r\n\r\n**Are you going to resolve the issue?**\r\nno sure - propably not..."},"comment":{"url":"https://api.github.com/repos/epoberezkin/ajv/issues/comments/396044499","html_url":"https://github.com/epoberezkin/ajv/issues/801#issuecomment-396044499","issue_url":"https://api.github.com/repos/epoberezkin/ajv/issues/801","id":396044499,"node_id":"MDEyOklzc3VlQ29tbWVudDM5NjA0NDQ5OQ==","user":{"login":"epoberezkin","id":2769109,"node_id":"MDQ6VXNlcjI3NjkxMDk=","avatar_url":"https://avatars3.githubusercontent.com/u/2769109?v=4","gravatar_id":"","url":"https://api.github.com/users/epoberezkin","html_url":"https://github.com/epoberezkin","followers_url":"https://api.github.com/users/epoberezkin/followers","following_url":"https://api.github.com/users/epoberezkin/following{/other_user}","gists_url":"https://api.github.com/users/epoberezkin/gists{/gist_id}","starred_url":"https://api.github.com/users/epoberezkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/epoberezkin/subscriptions","organizations_url":"https://api.github.com/users/epoberezkin/orgs","repos_url":"https://api.github.com/users/epoberezkin/repos","events_url":"https://api.github.com/users/epoberezkin/events{/privacy}","received_events_url":"https://api.github.com/users/epoberezkin/received_events","type":"User","site_admin":false},"created_at":"2018-06-10T12:14:59Z","updated_at":"2018-06-10T12:14:59Z","author_association":"OWNER","body":"@Hirntoasted it's fixed in 6.5.1, please test with your real code."}}
{"actor":{"display_login":"epoberezkin"}}