swagger-cli icon indicating copy to clipboard operation
swagger-cli copied to clipboard

Circular reference is considered an error

Open JFCote opened this issue 7 years ago • 17 comments

When you have a yaml model that reference itself, the validate function consider it an error, which is not. It is completely supported by tools like swagger-editor and swagger-codegen.

I'm using the latest release on npm (1.0.1).

To reproduce, use the petstore and add this in the definition part:

MenuItemDescription:
  type: string
  description: "List of all menu item descriptions"
  enum:
    - Choice1
    - Choice2
    - Choice3
MenuItem:
  type: object
  description: "Item in a menu"
  required:
    - description
    - childMenuItems
  properties:
    description:
      $ref: "#/definitions/MenuItemDescription"
    childMenuItems:
      type: array
      items:
        $ref: "#/definitions/MenuItem"

The error is as follow:

Swagger schema validation failed.
  Expected type object but found type string at #/definitions/$ref

JSON_OBJECT_VALIDATION_FAILED

Thanks!

JFCote avatar Nov 29 '17 15:11 JFCote

Circular references are fully supported. Please see the docs for more information.

The error message that you mentioned above does not appear to be due to a circular reference though. Can you post a complete code sample that reproduces the problem? I tried to reproduce the error using your example above, but it validated fine. Here's the Swagger file that I tested with:

swagger.yml

swagger: "2.0"
info:
  title: My API
  version: 1.2.3
paths:
  /:
    get:
      responses:
        default:
          description: Dummy response

definitions:
  MenuItemDescription:
    type: string
    description: "List of all menu item descriptions"
    enum:
      - Choice1
      - Choice2
      - Choice3
  MenuItem:
    type: object
    description: "Item in a menu"
    required:
      - description
      - childMenuItems
    properties:
      description:
        $ref: "#/definitions/MenuItemDescription"
      childMenuItems:
        type: array
        items:
          $ref: "#/definitions/MenuItem"

Using the above file (which contains a circular reference), I was able to successfully validate it using Swagger-CLI. Here's the console output:

swagger-cli validate swagger.yml
swagger.yml is valid

JamesMessinger avatar Nov 29 '17 16:11 JamesMessinger

You are right... I'm confused... I have this error in my big yaml file and I was sure that I had find the problem but it seems that it's not that. Let me double check my real yaml file to see if I can really find what is the problem.

JFCote avatar Nov 29 '17 17:11 JFCote

Ok I find a minimal way of reproducing it. It only happen with 2 files:

swagger.yaml

swagger: "2.0"
info:
  title: My API
  version: 1.2.3
paths:
  /:
    get:
      responses:
        default:
          description: Dummy response
definitions:
  $ref: ./definitions2.yaml

definitions.yaml

MenuItemDescription:
  type: string
  description: "List of all menu item descriptions"
  enum:
    - Choice1
    - Choice2
    - Choice3
MenuItem:
  type: object
  description: "Item in a menu"
  required:
    - description
    - childMenuItems
  properties:
    description:
      $ref: "#/MenuItemDescription"
    childMenuItems:
      type: array
      items:
        $ref: "#/MenuItem"

I have no clue what the problem is because if I put everything in the same file like I put in the original post, it work...

JFCote avatar Nov 29 '17 17:11 JFCote

Ok, cool. I was able to reproduce the problem. Looks like a bug in Swagger-Parser.

In the meantime, here's a workaround that I found:

swagger.yml

swagger: "2.0"
info:
  title: My API
  version: 1.2.3
paths:
  /:
    get:
      responses:
        default:
          description: Dummy response

definitions:
  MenuItemDescription:
    $ref: ./definitions.yml#/MenuItemDescription
  MenuItem:
    $ref: ./definitions.yml#/MenuItem

definitions.yml

MenuItemDescription:
  type: string
  description: "List of all menu item descriptions"
  enum:
    - Choice1
    - Choice2
    - Choice3
MenuItem:
  type: object
  description: "Item in a menu"
  required:
    - description
    - childMenuItems
  properties:
    description:
      $ref: "#/MenuItemDescription"
    childMenuItems:
      type: array
      items:
        $ref: "#/MenuItem"

Basically, you create a $ref for each type definition, rather than a single $ref for all the definitions. It's not as elegant, but it works for now. Another option would be to split definitions.yml into separate files for each type (e.g. MenuItemDescription.yaml and MenuItem.yaml)

JamesMessinger avatar Nov 29 '17 18:11 JamesMessinger

Thanks @BigstickCarpet !

Unfortunately, this fix is not possible as I have about 500 models. I'm 100% confident that this is a regression of swagger-parser because it was working a couple of days ago and this code didn't change.

Do you know when this will be fix?

Thanks!

JFCote avatar Nov 29 '17 18:11 JFCote

I can't say for sure how soon I'll have a fix, since I work on these projects in whatever spare time I have. Of course, I'd gladly accept a pull request if you have the time to fix it.

If this was previously working, then you can install an older version of Swagger-CLI and use that for the time being.

JamesMessinger avatar Nov 29 '17 19:11 JamesMessinger

@BigstickCarpet I tried with version 1.0.0 which I'm pretty sure was working but I think both version get the same version of the parser.

Unfortunately, I don't have time to work on the fix as all my time left is used to work on swagger-codegen but I will wait patiently for your fix!

Have a great day!

JFCote avatar Nov 29 '17 19:11 JFCote

FWIW, I've hit a different error that I'm pretty sure is still about recursion handling. I'm working on finding a minimal repro example. I'll post more details once I do, hopefully later today or some time tomorrow.

benhamill avatar Sep 06 '18 15:09 benhamill

OK. Here's the repro:

openapi.yaml

openapi: 3.0.1
info:
  title: Recusion Example
  version: 1.0.0
paths:
  /:
    get:
      $ref: get-root.yaml

get-root.yaml

x-definitions:
  Foo:
    type: object
    properties:
      foos:
        type: array
        items:
          $ref: "#/x-definitions/Foo"

responses:
  200:
    description: The root.
    content:
      application/json:
        schema:
          type: object
          properties:
            foo:
              $ref: "#/x-definitions/Foo"

Then run:

$ swagger-cli validate openapi.yaml
Swagger schema validation failed.
  Missing required property: responses at #/paths///get

JSON_OBJECT_VALIDATION_FAILED

The weird triple slash is because the middle slash is the name of the key for the path. IDK if there's a better way to format that, but it's saying that there's no responses key in my get definition. But there is.

If you just comment out the recursive Foo reference, it checks out.

To work around this, you can just inline the definition of get. Then it's OK even if Foo is in another file or whatever, AFAICT.

benhamill avatar Sep 06 '18 18:09 benhamill

Also, if you promote the responses key up to the main file, but keep everything below it in the second file like this:

openapi: 3.0.1
info:
  title: Recusion Example
  version: 1.0.0
paths:
  /:
    get:
      responses:
        $ref: get-root.yaml

Then the error is this:

Swagger schema validation failed.
  Additional properties not allowed: $ref at #/paths///get/responses

JSON_OBJECT_VALIDATION_FAILED

Which is at least reasonable because it's telling you it can't handle the $ref. But that doesn't seem to be the same problem as my first example, which can follow the $ref because it works if you take out the recursion.

benhamill avatar Sep 06 '18 18:09 benhamill

No solution for this bug yet?

jero-at-github avatar Feb 21 '20 10:02 jero-at-github

It seems there isn't solution but better error description, at least for swagger-cli bundle -r:

Circular $ref pointer found at /Users/name/go/src/github.com/repo/docs/myModel.yaml#/properties/elements/items

where elements/items:

myModel:
  properties:
    elements:
      items:
        $ref: "./myModel.yaml"
      type: array
      x-go-name: Elements

and swagger-cli validate gives swagger.yaml is valid

eugene-rockspoon avatar Jan 05 '21 14:01 eugene-rockspoon

Is there any solution for this ?

migue99angel avatar Apr 18 '22 11:04 migue99angel

+1

wudstrand avatar Aug 05 '22 19:08 wudstrand

Hello, I have found this thread today when I was searching for exactly this problem. I am getting exactly the same results as @eugene-rockspoon metioned. Funny fact I can validate my openApi.yaml spec locally (without error), but we are using it in gitlab CI and it fails. The version of swagger-cli is exactly the same in both enviroments (4.0.4). So this problem is still actual and I think it has to be resolved.

msandasyntea avatar Dec 14 '22 09:12 msandasyntea

+1

leevg avatar Jul 05 '23 13:07 leevg

any resolution to this?

usman-sadapay avatar Aug 16 '23 10:08 usman-sadapay