OpenAPI-Specification
OpenAPI-Specification copied to clipboard
The Response object's `default` field is confusing and inconsistently interpreted
According both 3.0 and 3.1, in theResponse
object there MUST be at least one response code and it SHOULD be the response for a successful operation call. In addition the default describes “responses other than the ones declared for specific HTTP response codes”.
This means that if we had a 200
response and default
, the latter would cover everything except for 200
. Many seem to interpret default
to mean something like response categories not covered by explicit response codes. Consider this example from the OAI org:
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore-expanded.yaml
This implies that default
covers error types when in fact it covers non-error responses as well. In fact, the consumer wouldn't necessarily know if the API might reply with another success code such as a 204
. A more precise example might look like this:
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
4xx:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
5xx:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
I would suggest the following actions:
- Update the example to interpret the spec more literally
- Clarify
default
since this confusion is not limited to this example, but extends to APIs in the wild - Consider in 3.2 or 4.0 eliminating
default
- Consider in 3.2 or 4.0 adding a new named
error
category that means "both 4xx and 5xx". This could be used in the way thatdefault
is often misused today
@ahl looking over this to see where it might fit in terms of releases and SemVer, I have a few questions:
- Why not simply use a
2XX
to exclude the other 200-series codes fromdefault
? The spec makes it clear that the200
response would take precedence over2XX
when an actual 200 response is returned. - Since Response Objects can be referenced, why not just
$ref
the same response from both4XX
and5XX
? That is two additional lines of spec, but that's not much in the grand scheme of OAS versbosity.
I agree that regardless, the wording of the examples is misleading, so I will tag this for 3.0.4 and 3.1.1 as those aspects should be fixed in those patch versions, regardless of what might happen in 3.2.
I'm also going to tag this as "3.0 needs documentation" because we could explain it on the learn.openapis.org site and I think that's what that label is for (@MikeRalphson @webron is that correct? I guess I could file it over on the OAI/Documentation repo instead?)
- Why not simply use a
2XX
to exclude the other 200-series codes fromdefault
? The spec makes it clear that the200
response would take precedence over2XX
when an actual 200 response is returned.
I want to describe an operation that
- responds with a 200 upon success and a particular response body
- does not respond with any other 2xx responses
- responds with a different response body with all 4xx and 5xx responses
In other words, if the API were to erroneously respond with a 204 there would be no guarantee that the response body conformed to the same schema as would, say, a 400 response.
- Since Response Objects can be referenced, why not just
$ref
the same response from both4XX
and5XX
? That is two additional lines of spec, but that's not much in the grand scheme of OAS versbosity.
I think that's the accurate way of describing the example. Why don't others just do that? I'd imagine they're being less precise, are confused, or are blithely following examples... from the OAI org.
What would you say an intended or well-formed use of default
? How would it be used on its own? How would it be used in concert with other, discrete status codes?
I agree that regardless, the wording of the examples is misleading, so I will tag this for 3.0.4 and 3.1.1 as those aspects should be fixed in those patch versions, regardless of what might happen in 3.2.
Again, consider this example: https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore-expanded.yaml
Do the operations return a single success code or might there be other ones? If the operation above responded with a 204 would its response body conform to #/components/schemas/Error
? Seems unlikely, but the definition of default
suggests that's the case.
@handrews the documentation
label definitely predates the learn.openapis.org site, however it is a good fit to indicate a PR against learn
would be appropriate.
I want to describe an operation that
- responds with a 200 upon success and a particular response body
- does not respond with any other 2xx responses
- responds with a different response body with all 4xx and 5xx responses
In other words, if the API were to erroneously respond with a 204 there would be no guarantee that the response body conformed to the same schema as would, say, a 400 response.
In my opinion, the onus is on you to document the known responses. When you say "if the API were to erroneously respond with a 204 there would be no guarantee that the response body conformed to the same schema as would, say, a 400 response", that's not an OpenAPI problem. If your API can return a 204
, you should document it as such unless it happens to have the same structure as default
...if you provide it. default
is only useful when you have a collection of status codes that have the same response structure, which in many/most cases error responses would apply. So to me, OpenAPI can't be expected to handle "erroneous [responses]" as that is a failure on the API to adhere to the contract.
In my opinion, the onus is on you to document the known responses.
On the API description author... sure! I would merely observe that mistakes have occurred in the past, and are likely to occur in the future.
So to me, OpenAPI can't be expected to handle "erroneous [responses]" as that is a failure on the API to adhere to the contract.
Perhaps the hypothetical was confusing. How about this:
Consider https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore-expanded.yaml
What response codes does, say, the addPets
operation respond with? One could infer that 200
is the only success response, but what in the OpenAPI spec tells us that this is so? If default
actually, de facto, is meant to describe "responses in http status code categories not covered by explicit or ranged response descriptions", then perhaps the spec should say that.
One could infer that 200 is the only success response, but what in the OpenAPI spec tells us that this is so? If default actually, de facto, is meant to describe "responses in http status code categories not covered by explicit or ranged response descriptions", then perhaps the spec should say that.
It does say that. It says, for the default
keyword:
The documentation of responses other than the ones declared for specific HTTP response codes.
So if you only document 200
and default
, your document is specifically saying that anything but 200 must conform to the schema specified for default
. If that references an Error schema, then you may conclude that there are no other 2xx (non-error) responses to be returned, and if the application does so it may be considered a violation of the schema.
One could infer that 200 is the only success response, but what in the OpenAPI spec tells us that this is so? If default actually, de facto, is meant to describe "responses in http status code categories not covered by explicit or ranged response descriptions", then perhaps the spec should say that.
It does say that. It says, for the
default
keyword:The documentation of responses other than the ones declared for specific HTTP response codes.
The additional detail I suggested was intentionally to distinguish it from the existing definition of "default". In particular the language "in categories not covered by explicit or ranged responses". This may be another case where more words would be clearer than fewer. My suggestion is that default would apply to status code ranges that are otherwise not mentioned. For example, if there is an entry for a 200, then default would not apply to the 2xx range. If there was a 404, default would similarly not apply to the 400 range.
Put perhaps another way. A common use of default is to cover the 4xx and 5xx range with an error response type. I think there would be utility in a spec being able to say "this is what a 200 response looks like and there will be no other 2xx responses".
Or perhaps "default" is insufficiently specific, and an "error" response that covers the 4xx and 5xx range would be more useful and intelligible.
if there is an entry for a 200, then default would not apply to the 2xx range. If there was a 404, default would similarly not apply to the 400 range.
This would be a breaking change, so it couldn't be done until OAS 4 "Moonwalk" where things are being re-imagined on a larger scale, including API-level responses. You might want to follow those discussions to see if there's an analogous concern with the new format.
On the one hand, I kind of like the error
idea, but since it's already possible to $ref
Response Objects, you can accomplish it by just $ref
-ing the same response from 4XX
and 5XX
. It doesn't seem worth adding more work for implementations just to save one reference.