diff --git a/chapters/http-status-codes-and-errors.adoc b/chapters/http-status-codes-and-errors.adoc index 3798913ba..0da555315 100644 --- a/chapters/http-status-codes-and-errors.adoc +++ b/chapters/http-status-codes-and-errors.adoc @@ -564,52 +564,74 @@ number of requests made within a given window for each named entity. == {MUST} support problem JSON {RFC-9457}[RFC 9457] defines a Problem JSON object using the media type -`application/problem+json` to provide an extensible human and machine readable -failure information beyond the HTTP response status code to transports the -failure kind (`type` / `title`) and the failure cause and location (`instant` / -`detail`). To make best use of this additional failure information, every -endpoints must be capable of returning a Problem JSON on client usage errors -({4xx} status codes) as well as server side processing errors ({5xx} status -codes). - -*Note:* Clients must be robust and *not rely* on a Problem JSON object -being returned, since (a) failure responses may be created by infrastructure -components not aware of this guideline or (b) service may be unable to comply -with this guideline in certain error situations. +`application/problem+json` to provide a standardized format for expressing +errors in API responses. It serves several purposes: -*Hint:* The media type `application/problem+json` is often not implemented as -a subset of `application/json` by libraries and services! Thus clients need to -include `application/problem+json` in the {Accept}-Header to trigger delivery -of the extended failure information. +* Developers: to debug, diagnose and resolve issues during API integration or + operation +* Client applications: to inform users about errors (in user interface) and to + support automated processing and error handling when appropriate. -The OpenAPI schema definition of the Problem JSON object can be found -https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml[on -GitHub]. You can reference it by using: +==== Problem schema members, suppported by the API guidelines +Problem detail objects can have the following members. -[source,yaml] ----- -responses: - 503: - description: Service Unavailable - content: - "application/problem+json": - schema: - $ref: 'https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml#/Problem' ----- +**Note:** If a member's value type does not match the specified type, +the member MUST be ignored -- i.e., processing will continue as if +the member had not been present. + +===== status (integer) +The HTTP status code generated by the origin server for occurrences of the problem. +Example: + + `"status": 400` + +===== title (string) +A short, human-readable summary of the problem type. It *SHOULD NOT* change +from occurrence to occurrence of the problem, except for purposes of +localization. +Example: + + `"title": "Invalid parameter"` + +===== detail (string) +A human-readable explanation specific to this occurrence of the problem. +Provides additional context or specifics about the error for debugging +or display to the user. +Example: -You may define custom problem types as extensions of the Problem JSON object -if your API needs to return specific, additional, and more detailed error -information. + `"detail": "The 'color' parameter is invalid"` -*Note:* Problem `type` and `instance` identifiers in our APIs are not meant -to be resolved. {RFC-9457}[RFC 9457] encourages that problem types are URI +===== type and instance (URI references) +The standardized Problem JSON object also allows for the following optional +members: + +- type: a URI identifying the problem type, typically more specific than the + HTTP status code. In many cases, an error code can be placed in the type + property. It may support automated client decisions in certain failure modes. + If the `type` doesn’t provide additional information, it can be omitted + (defaulting to `"about:blank"`). +- instance: a URI reference that identifies specific occurrence of the problem. + This field should serve the purpose of defining a clear error instance from + which the developer can determine the source location of the error. + Additionally, it may include relevant contextual information, such as parameters + associated with the error and optionally `Flow-ID` for debugging purposes. + +Examples: + +`"type": "https://example.com/errors/invalid-parameter"` + +`"type": "https://example.com/errors/ERR12345" (with error code)` + +`"instance": "/errors/12345"` + +*Note:* {RFC-9457}[RFC 9457] encourages that problem types are URI references that point to human-readable documentation, *but* we deliberately decided against that, as all important parts of the API must be documented using <<101, OpenAPI>> anyway. In addition, URLs tend to be fragile and not very stable over longer periods because of organizational and documentation changes and descriptions might easily get out of sync. -In order to stay compatible with {RFC-9457}[RFC 9457] we proposed to use +In order to stay compatible with {RFC-9457}[RFC 9457] we recommend to use https://tools.ietf.org/html/rfc3986#section-4.1[relative URI references] usually defined by `absolute-path [ '?' query ] [ '#' fragment ]` as simplified identifiers in `type` and `instance` fields: @@ -625,6 +647,129 @@ please reference https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.0.yaml#/Problem[problem-1.0.0.yaml#/Problem] instead. +==== Usage of Problem Object +Clients may utilize properties in the Problem Object, particularly those +documented in the API specification. However, they *should not* depend on these +properties being present or having specific values. +The examples of such cases are: + +- response might be created by infrastructure components (and have a different + response format, comparing to the guidelines) +- response might be created by a service that is unable to comply with the + guidelines due to certain error situations + +In cases where the Problem Object lacks the required information, clients must +implement fallback mechanisms, defaulting to reasonable behavior similar to +handling errors without a Problem Object provided. + +The OpenAPI schema definition of the Problem JSON object can be found +https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml[on +GitHub]. You can reference it by using: + +[source,yaml] +---- +responses: + 503: + description: Service Unavailable + content: + "application/problem+json": + schema: + $ref: 'https://opensource.zalando.com/restful-api-guidelines/models/problem-1.0.1.yaml#/Problem' +---- + +*Hint:* The media type `application/problem+json` is often not implemented as +a subset of `application/json` by libraries and services, thus clients need to +include `application/problem+json` in the {Accept}-Header to trigger delivery +of the extended failure information. + +==== Automated processing of Problem Object on client side +Problem details are often not described explicitly in the API and may evolve +over time. + +Unless the API defines and enumerates stable values for `type` and `instance` +with clear semantics, these fields *should not* be relied upon for client-side +automated decisions. + +The following guidelines offer best practices for utilizing type in automated +processing: + +1. Property `type` may be used by clients to make automatic decisions in + certain failure modes. The `title` property serves as a concise, + human-readable summary of the type. It is particularly helpful for debugging + and serves as an engineer-readable shorthand for the problem type. + +2. Clients may use these fields to drive automated actions if the API + explicitly defines the semantics of `type` and `instance` and enumerates + stable values. This can be achieved by extending the Problem JSON object and + associating an x-extensible-enum with the type property. + +3. Clients must handle scenarios where the type is absent or unrecognized and + fallback to default behaviors. + +4. For collections of related APIs, using shared type values for similar errors + and distinct values for different errors simplifies automated processing and + error handling for clients working across APIs. + +*Note:* Include descriptions for each known error that can happen directly in +the specification or reference external documentation to clarify their meanings +and intended use. + +==== Extensions of Problem Object schema +APIs can define custom fields in the Problem Object to provide more context +to meet specific application needs. +The custom fields should not conflict with the standard fields. +To extend the Problem Object, the API specification must define the custom +Problem, which would include Problem object members and custom ones. The +custom Problem can be used in the API specification as a reference, same as +a standard Problem object. +Example: +[source,yaml] +---- +components: + schemas: + Problem: + type: object + properties: + type: + type: string + format: uri + example: "https://example.com/errors/invalid-parameter" + title: + type: string + example: "Invalid Request Parameter" + status: + type: integer + example: 400 + detail: + type: string + example: "The 'color' parameter is invalid" + + CustomProblem: + allOf: + - $ref: "#/components/schemas/Problem" + properties: + errorCode: + type: string + example: "ERROR12345" + flowId: + type: string + example: "2914eefe-814e-4100-a332-42bac3352524" +---- + +*Note:* In case when client does not support some of the fields, +they should be ignored. + +==== Handling Multiple Errors in Batch/Bulk Responses +When an API processes batch requests, multiple errors may occur. +To ensure clarity and usability, the response should structure these errors +in a way that allows clients to identify and handle individual failures. + +Depending on the use-case the response can be structured in two ways: + +- as an array of Problem objects where each entry in the array represents an +individual error related to a specific request item. +- as a map where associated value contains the corresponding Problem object for +that specific request item. [#177] == {MUST} not expose stack traces