This page describes how service errors are returned by Rest.li and how they are documented in a resource’s IDL.
See Configuring Service Errors in Java for a step-by-step guide showing how to configure service errors in Rest.li Java.
All error responses are returned by Rest.li in a format conforming to the ErrorResponse schema, which contains various fields describing the service failure.
Field | Description |
---|---|
status |
The HTTP status code. |
code |
The canonical error code, e.g. for ‘400 Bad Request’ it can be ‘INPUT_VALIDATION_FAILED’. Only predefined codes should be used. |
message |
A human-readable explanation of the error. |
docUrl |
URL to a page that describes this particular error in more detail. |
requestId |
The unique identifier that would identify this error. For example, it can be used to identify requests in the service’s logs. |
exceptionClass |
The FQCN of the exception thrown by the server. |
stackTrace |
The full stack trace of the exception thrown by the server. |
errorDetailType |
The type of the error detail model, e.g. com.example.api.BadRequest. Clients can use this field to identify the actual error detail schema. |
errorDetails |
This field should be used for communicating extra error details to clients. |
Here is an example error response serialized to JSON as it would be sent over the wire and received by the client. This
scenario involves a client which has used up its daily quota for a particular service, triggering the resource method to
throw a fictitious QuotaExceededException
. The error details object conforms to the fictitious QuotaDetails
schema,
which contains relevant information about the quota usage.
Please note that the stack trace has been truncated for the sake of space.
{
"status": 429,
"code": "QUOTA_EXCEEDED",
"message": "You've exceeded your daily request quota.",
"docUrl": "https://example.com/docs/errors/QUOTA_EXCEEDED",
"requestId": "cgA4qNoE48AJabrC",
"exceptionClass": "com.example.QuotaExceededException",
"stackTrace": "Exception in thread \"main\" com.example.QuotaExceededException: ...",
"errorDetailType": "com.example.api.QuotaDetails",
"errorDetails": {
"interval": "DAILY",
"quota": 10000,
"usage": 10034
}
}
By default, Rest.li returns the error response containing all the fields described above, in addition to
an X-RestLi-Error-Response
HTTP header. However, Rest.li supports returning only a subset of these fields.
In Java, the RestLiConfig
class is used to configure which ErrorResponse
fields should be included
in the response.
Using a predefined error response format to only return the status, code, and message:
restLiConfig.setErrorResponseFormat(ErrorResponseFormat.MESSAGE_AND_SERVICECODE);
{
"status": 429,
"code": "QUOTA_EXCEEDED",
"message": "You've exceeded your daily request quota."
}
Creating a custom subset of fields to return:
EnumSet<ErrorResponseFormat.ErrorResponsePart> parts = EnumSet.of(HEADERS,
STATUS_CODE_IN_BODY,
DOC_URL,
STACKTRACE);
restLiConfig.setErrorResponseFormat(new ErrorResponseFormat(parts));
{
"status": 429,
"docUrl": "https://example.com/docs/errors/QUOTA_EXCEEDED",
"stackTrace": "Exception in thread \"main\" com.example.QuotaExceededException: ..."
}
Semantically, an error response is still a valid API response – it’s one of the possible outputs of an API call - so it must be part of the formal contract. Having well-documented service errors as part of an API enables clients to handle failures resiliently, and allows developers to intelligently prepare their clients for failures.
For a full, in-depth example of what an IDL looks like documented with service errors and success codes, see AlbumEntryResource and its generated IDL.
If a resource has been given a set of service errors (done in Java using @ServiceErrors
, see
here), those service errors will be documented in the IDL as a list of
objects, each containing the HTTP status code, the application-specific string error code, the message, and the
error detail type (for each that is present). For example, a resource someResource
that may fail due to some
rate-limiting restrictions will be documented in the IDL as:
{
"name" : "someResource",
...
"collection" : {
"serviceErrors" : [ {
"status" : 429,
"code" : "QUOTA_EXCEEDED",
"message" : "You've exceeded your daily request quota.",
"errorDetailType" : "com.example.api.QuotaDetails"
} ],
...
}
...
}
If a resource has been given a set of service errors (done in Java using @ServiceErrors
or @ParamErrors
, see
here), those service errors will be documented in the IDL as a list of
objects similar to what is shown above. The difference here is that these will be documented per-method, and also
support indicating specific parameter names. For example, a finder
method that may fail on some parameter albumId
will documented in the IDL as:
{
"serviceErrors" : [ {
"status" : 422,
"code" : "INVALID_ID",
"message" : "Id cannot be less than 0",
"errorDetailType" : "com.example.api.IdError",
"parameters" : [ "albumId" ]
} ],
"name" : "search",
"parameters" : [ {
"name" : "albumId",
"type" : "long",
}
}
If a resource method has been given a set of success codes (done in Java using @SuccessResponse
), those success codes
will be documented in the IDL as a list of integers. For example, a get
method that returns an HTTP 200
response on
success will be documented in the IDL as:
{
"success" : [ 200 ],
"method" : "get",
"doc" : "Gets a thing."
}
Making changes to the service error information in a resource’s IDL has an impact on the compatibility checker.
The following changes are considered backward compatible:
The following changes are considered backward incompatible:
errorDetailType
for an existing service error code.status
code for an existing service error code.message
for an existing service error code.