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

False error oas3-valid-schema-example reference resolves to more than one schema #2081

Closed
DavidBiesack opened this issue Mar 7, 2022 · 12 comments · Fixed by #2408 or #2561
Closed
Assignees
Labels

Comments

@DavidBiesack
Copy link

For support questions, please use the Stoplight Discord Community. This repository's issues are reserved for feature requests and bug reports. If you are unsure if you are experiencing a bug, our Discord is a great place to start.

Please delete this section, any any sections below that you don't use, before creating the issue.

Describe the bug
Spectral is generating a strange error when a schema has a property with the name id.

To Reproduce

  1. Given this OpenAPI/AsyncAPI document
openapi: 3.0.3
info:
  title: Spectral Issue
  description: >-
    error oas3-valid-schema-example reference "bf23bc970b78d27691e8" resolves to more than one schema
  version: 0.1.0
  contact:
    name: Apiture

servers:
  - url: /spectral/issues

tags:
  - name: Spectral Issues
    description: Spectral Issues

paths:

  /path:
    get:
      operationId: getResource
      description: Get a resource
      tags:
        - Spectral Issues
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/collection"


components:

  schemas:

    item:
      type: object
      properties:
        id:
          description: >-
            The unique identifier for this account resource.
            This is an immutable opaque string.
          readOnly: true
          type: string
          pattern: '^[-_:.~$a-zA-Z0-9]+$'
          minLength: 6
          maxLength: 48
          example: bf23bc970b78d27691e8
        url:
          description: >-
            The URL of this account instance. See the [`getAccount`](#op-getAccount) operation.
          readOnly: true
          maxLength: 256
          type: string
          format: uri
          example: https://api.apiture.com/banking/accounts/bf23bc970b78d27691e8
      example:
        id: bf23bc970b78d27691e8
        url: https://api.apiture.com/banking/accounts/bf23bc970b78d27691e8

    collection:
      required:
        - items
      type: object
      allOf:
        - type: object
          properties:
            items:
              description: The array of items in this page of accounts.
              readOnly: true
              type: array
              items:
                $ref: '#/components/schemas/item'
      example:
        items:
          - id: bf23bc970b78d27691e8
            url: https://api.example.com/spectral/issues/bf23bc970b78d27691e8
          - id: 8d27691e8bf23bc970b7
            url: https://api.example.com/spectral/issues/8d27691e8bf23bc970b7

and this .spectral.yaml
3. Run this CLI command: spectral lint -r ./.spectral.yaml openapi.yaml
4. See error

spectral lint -r ./.spectral.yaml openapi.yaml

./spectral-issues/openapi.yaml
 76:15  error  oas3-valid-schema-example  reference "bf23bc970b78d27691e8" resolves to more than one schema  components.schemas.collection.example

✖ 1 problem (1 error, 0 warnings, 0 infos, 0 hints)

Expected behavior

There should be no error here.

Environment (remove any that are not applicable):

@DavidBiesack
Copy link
Author

The error goes away if I globally change id: to resourceId:, or if I remove either of the the example objects in the collection or item schemas or just the first array item in the example in collection.

@DavidBiesack
Copy link
Author

The error seems to be coming from ajv which is validating the examples against the schema; ajv is compiling the schemas from #/components/schemas/* and does not know about the example object that OpenAPI defines, so it is interpreting the id as as schema id. I think spectral needs to remove the example object.

addRef (~/dev/tools/spectral/node_modules/ajv/lib/compile/resolve.ts:112)
<anonymous> (~/dev/tools/spectral/node_modules/ajv/lib/compile/resolve.ts:105)
_traverse (~/dev/tools/spectral/node_modules/json-schema-traverse/index.js:69)
_traverse (~/dev/tools/spectral/node_modules/json-schema-traverse/index.js:75)
_traverse (~/dev/tools/spectral/node_modules/json-schema-traverse/index.js:83)
module.exports (~/dev/tools/spectral/node_modules/json-schema-traverse/index.js:14)
getSchemaRefs (~/dev/tools/spectral/node_modules/ajv/lib/compile/resolve.ts:101)
_addSchema (~/dev/tools/spectral/node_modules/ajv/lib/core.ts:706)
compile (~/dev/tools/spectral/node_modules/ajv/lib/core.ts:377)
<anonymous> (~/dev/tools/spectral/packages/functions/src/schema/ajv.ts:93)
schema (~/dev/tools/spectral/packages/functions/src/schema/index.ts:49)
schema (~/dev/tools/spectral/packages/core/src/ruleset/rulesetFunction.ts:136)
oasSchema (~/dev/tools/spectral/packages/rulesets/src/oas/functions/oasSchema.ts:61)
oasSchema (~/dev/tools/spectral/packages/core/src/ruleset/rulesetFunction.ts:136)
oasExample (~/dev/tools/spectral/packages/rulesets/src/oas/functions/oasExample.ts:153)
oasExample (~/dev/tools/spectral/packages/core/src/ruleset/rulesetFunction.ts:136)
lintNode (~/dev/tools/spectral/packages/core/src/runner/lintNode.ts:30)
cb (~/dev/tools/spectral/packages/core/src/runner/runner.ts:52)
mapped.<computed> (~/dev/tools/spectral/packages/core/src/runner/runner.ts:109)
_callbacks.<computed> (~/dev/tools/spectral/node_modules/nimma/dist/legacy/cjs/runtime/proxy-callbacks.js:31)

Note that example is deprecated in OAS 3.1 in favor of examples in JSON Schema, but it is not yet
deprecated in OAS 3.0.x which the example is using.
I can't switch to OAS 3.1, as other tools we use do not yet support it.

@hudlow
Copy link

hudlow commented Apr 29, 2022

@DavidBiesack Thanks for the work tracking this down. I ran into it independently in case another test case is useful: #2140

@sudoku-lord
Copy link

Is there any update on this issue? It's causing problems for me.

@bwl21
Copy link

bwl21 commented Jun 20, 2022

@DavidBiesack

I dropped in the same issue while using stoplight studio. I found ajv-validator/ajv#1426 which seems to deal with the same thing.

The error seems to be coming from ajv which is validating the examples against the schema; ajv is compiling the schemas from #/components/schemas/* and does not know about the example object that OpenAPI defines, so it is interpreting the id as as schema id. I think spectral needs to remove the example object.

If this is true, then it appears to be a bug i stoplight studio. When validating the examples, only the schema relevant for the example should be provided to AJV but not the openapi schema, and also not all schemas within the openapi instance.

the openapi schema says in https://swagger.io/specification/#example-object that "examples" can be any. So stoplight should not mess up the schema for openapi and the schemas mentioned within an openapi specification.

@venilillkall
Copy link

Would be great to get this fixed - we have an API spec that has loads of these, it's super annoying

@DavidBiesack
Copy link
Author

a workaround is to use unique id values in all the examples, although this is not always possible.

@venilillkall
Copy link

yes, we also managed to work around this as suggested, but just having to do that is plain silly

@padamstx
Copy link
Contributor

Any chance we could get some attention on this issue? My team supports a spectral-based validator along with a ruleset that inherits the spectral:oas ruleset, and we've received reports of this problem with the oas3-valid-schema-example rule, along with reports of a similar issue in the oas3-valid-media-example rule as well.

@padamstx
Copy link
Contributor

There might be some hope for this one yet... for the last couple of days, I've been studying the code related to the oas3-valid-schema-example & oas3-valid-media-example rules and trying to understand what's going on. I have a hunch that the resolves to more than one schema error is occurring during the schema compilation with ajv, not during the actual validation of the example value. Also, @DavidBiesack mentioned above:

I think spectral needs to remove the example object.

So with this in mind, and the fact that I really didn't have any other leads 😂, I modified the oasExample() rule function a bit so that it removes any "example" fields in the schema that it's going to pass into oasSchema() to do the actual schema validation of the example value. Surprisingly, that was enough to avoid the false errors. I figured the oasExample() function was the best place to do this, so that other invocations of oasSchema() are not subject to this example filtering.

I still have more testing to do, but I'll try to get a PR opened up for this soon.

padamstx added a commit to padamstx/spectral that referenced this issue Feb 22, 2023
This commit modifies the oasExample function so
that example fields are removed from the schema
to be used for validation.  This is needed because
the presence of an "example" field in a schema
confuses ajv in certain scenarios.
References:
- stoplightio#2081
- stoplightio#2140
- ajv-validator/ajv#1426
@padamstx
Copy link
Contributor

@DavidBiesack I've opened a PR that fixes this issue in case you'd like to give it a try.

padamstx added a commit to padamstx/spectral that referenced this issue Feb 23, 2023
This commit modifies the oasExample function so
that example fields are removed from the schema
to be used for validation.  This is needed because
the presence of an "example" field in a schema
confuses ajv in certain scenarios.
References:
- stoplightio#2081
- stoplightio#2140
- ajv-validator/ajv#1426
travisgosselin added a commit to SPSCommerce/sps-api-standards that referenced this issue Feb 24, 2023
Specifically needed to update 2 rules causing issues with examples:

oas3-valid-media-example - causing issues in very weird circumstances with examples that shouldn't be failing. But in spectral? stoplightio/spectral#2081

Custom rule sps-ref-property-name - causing issues in indicating examples needed to use format.
padamstx added a commit to padamstx/spectral that referenced this issue Mar 1, 2023
This commit modifies the oasExample function so
that example fields are removed from the schema
to be used for validation.  This is needed because
the presence of an "example" field in a schema
confuses ajv in certain scenarios.
References:
- stoplightio#2081
- stoplightio#2140
- ajv-validator/ajv#1426
albertyfwu added a commit to supaglue-labs/supaglue that referenced this issue Mar 10, 2023
Most of the issues here are due to ajv having a bug and interpreting
`id: <uuid>` as schema id even when they're used in examples. See
stoplightio/spectral#2081

Also, we seem to be mixing openapi 3.0.3 and 3.1.0 syntax for examples,
which we should clean up at some point.
padamstx added a commit to padamstx/spectral that referenced this issue Apr 5, 2023
This commit modifies the oasExample function so
that example fields are removed from the schema
to be used for validation.  This is needed because
the presence of an "example" field in a schema
confuses ajv in certain scenarios.
References:
- stoplightio#2081
- stoplightio#2140
- ajv-validator/ajv#1426
P0lip added a commit that referenced this issue Apr 25, 2023
* fix(rulesets): avoid false errors from ajv

This commit modifies the oasExample function so
that example fields are removed from the schema
to be used for validation.  This is needed because
the presence of an "example" field in a schema
confuses ajv in certain scenarios.
References:
- #2081
- #2140
- ajv-validator/ajv#1426

* docs(repo): fix lint warning in README

Signed-off-by: Phil Adams <phil_adams@us.ibm.com>

* chore(rulesets): use traverse

---------

Signed-off-by: Phil Adams <phil_adams@us.ibm.com>
Co-authored-by: Jakub Rożek <jakub@stoplight.io>
P0lip added a commit that referenced this issue Apr 25, 2023
* fix(rulesets): avoid false errors from ajv

This commit modifies the oasExample function so
that example fields are removed from the schema
to be used for validation.  This is needed because
the presence of an "example" field in a schema
confuses ajv in certain scenarios.
References:
- #2081
- #2140
- ajv-validator/ajv#1426

* docs(repo): fix lint warning in README

Signed-off-by: Phil Adams <phil_adams@us.ibm.com>

* chore(rulesets): use traverse

---------

Signed-off-by: Phil Adams <phil_adams@us.ibm.com>
Co-authored-by: Jakub Rożek <jakub@stoplight.io>
@mnaumanali94 mnaumanali94 reopened this Nov 21, 2023
@stoplight-bot
Copy link
Collaborator

🎉 This issue has been resolved in version 1.18.1 🎉

The release is available on @stoplight/spectral-rulesets-1.18.1

Your semantic-release bot 📦🚀

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