Two flags, true or false, say what a value may lack, and they are independent of each other:
optional: truesays the key may be missing. It is accepted only on a property, with or without arefbeside it. A property is required unless it says so; there is norequiredlist.nullable: truesays the key is there and its value may benullor the declared type. It is accepted on any node: a property,items,valuesand the root of a schema.
User: type: object properties: avatar: # always there, may be null type: string nullable: true nickname: # may be missing type: string optional: true bio: # may be missing, may be null type: string optional: true nullable: true
optional on a named schema, on array items or on map values is rejected at publish, optional: false too. A named schema is not optional by itself: the property that uses it is, with optional: true beside its ref:
contract validation failed - petstore_api.yaml: "optional" is not allowed on a schema at schemas Pet, mark optional the property that uses it, beside its "ref"
In the same way, when an array or a map may be missing, the property that holds it is optional, and an element or a value that may be null takes nullable: true on items or values; Arrays and Maps show their error lines.
How each side writes the flags from what its code does is in Describe what the code does, and what they mean for a break is in Which side decides.