Skip to content

openapi: 3.2-only schema keywords are validated against the 3.1 meta-schema #146

Description

@OmarAlJarrah

A conformant OpenAPI 3.2 document that uses a 3.2-only schema object keyword fails to compile
with an error diagnostic, so under the CLI default of --fail-on error morphic compile exits 1
on a valid spec.

openapi: 3.2.0
info: {title: p, version: "1"}
paths: {}
components:
  schemas:
    Pet:
      type: object
      required: [petType]
      properties:
        petType: {type: string}
      discriminator:
        propertyName: petType
        defaultMapping: "#/components/schemas/Cat"
        mapping:
          cat: "#/components/schemas/Cat"
    Cat:
      allOf: [{$ref: "#/components/schemas/Pet"}]
$ morphic compile spec.yaml -o /dev/null
error openapi/validation/validation-invalid-schema spec.yaml#13:25: [13:25] error
  validation-invalid-schema schema.discriminator.defaultMapping false schema
exit status 1

Why

speakeasy-api/openapi@v1.24.0, jsonschema/oas3/jsonschema.go:262JSONSchema[T].Validate
discards its options and calls schema.Validate(ctx) with none, carrying a "for now" comment. So
ParentDocumentVersion never reaches schema validation and every schema object is checked against
the 3.1 meta-schema regardless of the document version. The 3.1 $defs/discriminator sets
unevaluatedProperties: false and does not declare defaultMapping, so a 3.2 document fails
against a schema that forbids the keyword it legitimately writes.

Confirmed directly against the library: oas3.Validate with
ParentDocumentVersion{OpenAPI: "3.2.0"} returns 0 errors, and with "3.1.0" returns exactly the
error above.

Blast radius

This is not specific to defaultMapping — it affects any 3.2-only keyword that lives on a schema
object. defaultMapping is simply the one that surfaced. Document-level 3.2 additions are
unaffected, because those do not route through schema validation.

Consequences beyond the exit code

Discriminator.Default has no corpus witness and cannot get one while this stands: its only source
is defaultMapping, and a corpus spec declaring it emits an error diagnostic, which the conformance
harness treats as a failure. The gap is noted in
testdata/conformance/openapi/discriminator-inheritance.yaml, which declares the surrounding
discriminator inheritance shape but deliberately omits defaultMapping.

Options

Bump the library once the option-dropping is fixed upstream, or suppress this specific
false positive in load.go the way the numeric-literal artifact already is — matching on the
version/keyword pair rather than on message text, so it stops applying as soon as the library is
correct.

Method

Compiled the spec above through the CLI and through openapi.New().Compile(...); isolated the cause
by calling the library validator directly with each ParentDocumentVersion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions