API Error Reporting Guidelines¶
Introduction¶
Our goal is to harmonize the reporting of errors for API clients. The representation of an error should be no different than the representation of any resource, just with its own set of fields. In addition to use HTTP error codes, which are often too coarse to guide the API client to solve the problem, we apply an extensible approach for the possible wide range of error types. This set of rules harmonizes all APIs reporting errors to API clients. The interoperability of the format reduces efforts for the API producer as well as on the API client side.
Most of the time in development is spent for reading and understanding the code. Therefore, a fast understanding of reported errors of an API is very important. The API error guidelines assure that enough information to handle client-side and server-side errors in a consistent way such as unauthorized, retry timespans, or a maximum of calls per timespan will be provided and the developers of the API clients have a consistent way to handle reported errors simpler.
This page provides guidance on how an API developer must implement an error handling approach to handle reported errors of the APIs. If the API reports errors as it is covered in this page, an API client is able to inspect the error and find an appropriate solution.
API MUST use official HTTP status codes as intended [300]¶
An API MUST consistently use official HTTP status codes only with their intended semantics. The official HTTP status codes are defined and registered at:
- RFC 9110 - HTTP Semantics (obsoletes 7232, 7235)
- RFC 2616: Hypertext Transfer Protocol - HTTP/1.1, section 6.1.1 “Status code and Reason Phrase”
- IANA Status Code Registry
- RFC 6585 - HTTP: Additional Status Codes
The rule 301 lists the supported error codes. The different 4xx HTTP status codes
are used for errors caused by API client side and 5xx HTTP status codes
reports server side errors.
API SHOULD only use most common HTTP status codes [301]¶
An API SHOULD use the most commonly used codes as these are best understood. You SHOULD avoid less commonly used codes or own error codes that may create misconceptions and misunderstandings due to less familiar semantics. If the API has to report a HTTP error code which is not covered in the list below, the API specification MUST define the semantic of the error code.
Response codes MUST be documented in the API documentation, if the API reports or supports these error types. The official HTTP status codes are grouped in the following four classes. These HTTP status codes need to be used consistently with their intended semantics as per the RFC standards.
No extensions to cited RFC
The following status codes are not changed to the referenced RFC 9110 and RFC 6585. These status codes are listed to provide you a comprehensive, self-contained and complete overview of the most used HTTP status codes. The RFCs and IANA offer more status codes but these are not common for REST API and you should use them consciously and carefully only.
Client Error 4xx Status Codes [301.3]¶
Code | Response | Description | Methods |
---|---|---|---|
400 | Bad Request | The request could not be processed by the server because the request is perceived as client error (such as, malformed request syntax, invalid request message framing, or deceptive request routing). The API client MUST change its request to proceed. | all |
401 | Unauthorized | The API client is not providing valid authentication credentials for the target resource. The server generating a 401 response MUST send a WWW-Authenticate header field containing at least one challenge applicable to the target resource. If the request included authentication credentials, then the 401 response indicates that authorization has been refused for those credentials (such as, expired token). | all |
403 | Forbidden | The API client is not allowed to access the resource. The API client SHOULD not repeat the request. In contrast to error code 401 the server understood the request and the provided authentication credentials, but refuses to authorize the API client. Only use if user has read access, otherwise always use 404 for security reasons to hide the existence of resource. | POST, PUT, PATCH, DELETE |
404 | Not Found | The resource is not found. The service did not find a current representation for the target resource or is not willing to disclose that one exists. A 404 status code does not indicate whether this lack of representation is temporary or permanent; the 410 (Gone) status code is preferred over 404 if the origin server knows, presumably through some configurable means, that the condition is likely to be permanent. | all |
405 | Method Not Allowed | The method received in the request-line is known by the origin server but not supported by the target resource. The service MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods. | all |
406 | Not Acceptable | The service is not able or willing to respond using the request media-type or representation asked by the API client in the Accept header. The server SHOULD generate a payload containing a list of available representation characteristics and corresponding resource identifiers from which the user or user agent can choose the one most appropriate. | all |
408 | Request Timeout | The request timed out because a server did not respond within the expected waiting time. A server SHOULD send the "close" connection option in the response, since 408 implies that the server has decided to close the connection rather than continue waiting. Note this response is often generated on gateways in the communication path. | all |
409 | Conflict | The request is not executed because of a conflict with the current state of the target resource, such as concurrent or duplicate request. The API client needs to decide how to continue, but it is expected that the API client is able to resolve the conflict to proceed. | POST, PUT, PATCH, DELETE |
412 | Precondition Failed | The request failed to process because the service evaluated the conditions given in the request header to false, such as If-Match conditions for optimistic locking. The response status code allows the API client to place preconditions on the current resource state (its current representations and metadata) and, thus, prevent the request method from being applied if the target resource is in an unexpected state. | PUT, PATCH, DELETE |
415 | Unsupported Media Type | The request body (payload) is in a format or media type that the server does not support. The format problem might be due to the request's indicated Content-Type or Content-Encoding , or as a result of inspecting the data directly. | POST, PUT, PATCH, DELETE |
429 | Too Many Request | The API client has sent too many requests in a given timespan. The response SHOULD include details explaining the condition. The response SHOULD include the Retry-After header field indicating how long to wait before making a new request. | all |
Server Error 5xx Status Codes [301.4]¶
Code | Response | Description | Methods |
---|---|---|---|
500 | Internal Server Error | An unexpected error occurred and the server is not fulfilling the request. Please consider the NOT Expose Stack Traces of Your Error rule. | all |
501 | Not implemented | The server is not supporting the request. This is the appropriate response when the server does not recognize the request method and is not capable of supporting it for any resource. Return status code 405 has preference over 501. | all |
503 | Service Unavailable | The service is temporary not available due to overload or maintenance. The server MAY return the Retry-After header to suggest an appropriate time to wait for the API client before retrying the request, for example, the maintenance window ends in x minutes. | all |
API SHOULD use most specific HTTP status code for error [302]¶
An API SHOULD use the most specific HTTP status code when returning information about the request processing state or reported error situations.
API SHOULD not expose stack traces of the error [303]¶
An API reports errors, but it SHOULD NOT expose stack traces. Firstly, stack traces are not part of an API specification, secondly API clients should never rely on stack traces to change a request. Moreover, stack traces expose sensitive information of the code and its dependencies that partners and third parties are not allowed to receive and may disclose unintended insights about vulnerabilities to attackers.
Additionally, the other property of a JSON error object can expose sensitive information of the code and its dependencies. Therefore the reported errors SHOULD be evaluated in a threat and risk analysis if the reported information offers an attack vector on the Xcelerator service.
API SHOULD report problems with an errors
object [304]¶
Errors SHOULD be described in the error objects. In the response, the top level member is the errors
object for API. The errors
collection MUST not be empty but contain at least one error object.
With the error object, the raised problem is communicated to the API client to react accordingly. errors
are intended to explain 4xx or 5xx HTTP status codes in more detail. The errors
collection SHOULD report all known and identified problems from the API to the API client. The list of errors contains all known occurred errors on the backend. The objective is to avoid a step-wise exploration of issues until all are fixed. Of course in case of a distributed system not all errors are known in advance, but what could be validated, SHOULD be reported to the API client.
Error object SHOULD be represented according to the defined structure fields [305]¶
Each error object within the errors array MUST NOT be empty and MUST contain at least one of the following attributes:
field | description |
---|---|
id | A unique identifier for this particular occurrence of the problem. |
code | An application-specific error code, expressed as a string value. The format and type of code representation (such as, numeric values or hex values) MUST be harmonized across all error codes within an application. The code focuses on programs and doesn’t have to be human-readable. |
status | Numeric HTTP status code for the specific error. |
title | Developer friendly, human-readable description or summary that SHOULD NOT change from occurrence to occurrence of the problem. In case of using a custom HTTP status codes in the status field of the error object, the title MUST provide a concise description of the HTTP error code (for example: status : "599", title : "Network Connection Timeout"). |
detail | Developer friendly, human-readable, detailed description specific to the occurrence of the problem. |
links | A links object is a resource object in its own. links point to further information for the reported error to support the developer to fix the problem. |
correlationId | A unique string identifier, e.g. a UUID, representing a flow through the system. It can be used for tracing and debugging, see Best Practices. |
An API MAY provide additional attributes.
Usage of the property code
in error object
Be aware of the possibility to misuse the code
for hack attacks. Consider the rule to Not Expose Stack Traces of Your Error" for not exposing the call stack of the application, the same is valid for the application specific code
. Values like Access Violation provides more details about the root cause.
Extending the property code
to track error origin
In a distributed system, such as, microservices architecture there are transitive calls happening. To state the origin of the error, the calling service MAY report the received error to its caller too. To differ the origin of the errors in the list, the code
can be prefixed with an abbreviation of the service, like "sgp:0x80003033
" to report, that the error 0x80003033
was initially reported by service sgp (Siemens GPS Position service). This common practice improves the inspectability and understandability of errors. But the prefix SHOULD NOT expose too much details for the application system architecture.
The links
resource object MAY contain the following members:
about
: MUST provide a URI that redirects to further details about this particular occurrence of the error. When opened, this URI SHOULD return a human-readable description of the error for the developer to investigate.type
: MUST provide a URI that identifies the type of error that this particular error belongs to. The URI points to a human-readable explanation of the error type for the developer to investigate.
Here is an example of a simple error response.
{
"errors": [
{
"code": "0x80003033"
}
]
}
In the above example HTTP header already includes status
and title
, so there is no need of repetition.
In case the application wants to point in the error object to the primary source of the problem, the property source
MAY be used. The source
object SHOULD include one of the following members or be omitted:
pointer
: a RFC6901 JSON Pointer to the value in the request document that caused the error (for example, "/data" for a primary data object, or "/data/attributes/title" for a specific attribute). This MUST point to a value in the request document that exists; if it doesn’t, the API client SHOULD simply ignore the pointer.parameter
: a string that indicates which URI query parameter caused the error.header
: a string that indicates the name of the header property which caused the error.
Here is an example of a detailed error response.
{
"errors": [
{
"id": "eec33bf0-6bcc-4813-ae7e-0a70e8e53c3b",
"code": "0x00000001",
"status": 415,
"title": "Unsupported Media Type",
"detail": "The requested content type is not supported",
"source": {
"header": "content-type"
},
"links": {
"about": "https://applicationx.siemens.net/validation-error/overview/#content-type",
}
},
{
"id": "e043cedd-600c-468c-8563-d4e591e3ba89",
"code": "0x30005553",
"detail": "the device name must not include any other characters than a-z, A-Z, 0-9, - and _",
"title": "Unprocessable Content",
"source": {
"pointer": "/device/attributes/deviceName"
},
"links": {
"about": "https://applicationx.siemens.net/validation-error/overview/#devices",
}
},
{
"id": "fd5864bd-3233-4f8d-9da2-734910be43bb",
"code": "0x80003033",
"status": 410,
"detail": "The device with name is already gone"
}
]
}