Contribute to help us improve!
Are there edge cases or problems that we didn't consider? Is there a technical pitfall that we should add? Did we miss a comma in a sentence?
If you have any input for us, we would love to hear from you and appreciate every contribution. Our goal is to learn from projects for projects such that nobody has to reinvent the wheel.
Let's collect our experiences together to make room to explore the novel!
To contribute click on Contribute to this page on the toolbar.
RESTful Exception Handling
This article gives advice on a proper exception handling in the service layer. It is important to catch all exceptions and map them to a meaningful result and not pass implementation details to the outside. If not handled correct a generated error message is send to the client.
Use RFC 7807 for error responses
RFC7807 defines a "problem detail" so no new response formats need to be defined. It’s recommended to go with the described format. In the following chapters a few recommendations based on the RFC are documented
Do not use URLs
The RFC describes at least title and instance to be URIs. Often readers imagine callable URLs at this place, which leads to a lot of complex solutions ideas. Consider using URNs instead of URLs to be most flexible and still aligning with the specification.
Define a problem type and title as constant string
The type should be a URN that identifies the underlying error.
Use urn:problem:<error-code>
as type.
<error-code>
should identify the underlying error and should not change.
The classname e.g. is not a good error-code as it might change due to refactoring work.
It’s best to have a mapping of exception class to error-code.
It’s recommended to use a String representation of the error like ValidationError, ResourceNotFound. But it could also be a number.
The title should be a human understandable definition of the type. The same type should always match to the same title. E.g.: ValidationError - The request was not valid. ResourceNotFound - A resource was not found
The details can be used to provide further information like the Validation Problems or the id and type of the resource that was not found.
Use a unique identifier to define the instance
The instance should identify the concrete error that occurs.
It’s recommended to use a UUID to define this.
urn:uuid:<UUID>
In cases where there’s a trace-id this could be used. This way it’s easiest for the operations team to quickly identify the requests related to the error.
If no ID can be reused that marks the error instance, a new UUID should be created and logged out together with helpful information.
Use an OpenAPI specification to define the problem details
OpenAPI can be used to define and generate the problem details. This is especially helpful, when additional attributes are used, that are not defined by the specification. That way the caller can expect further information and display it.
When inheritance for the problem details is used in the OpenAPI spec, define an additional _schema
attribute as discriminator for the concrete type. For more details take a look at the openAPI specification.
Exception Types
Special exceptions have clear requirements regarding the information that is exposed.
Do not expose any information on Security Exceptions
HTTP status code |
403 (FORBIDDEN) |
type |
about:blank |
title |
"forbidden" |
details |
empty |
instance |
An identifier (generally the correlation id) to help identify corresponding requests in logs |
Log all validation errors of Validation Exceptions
Validation errors include all validation issues that do not fullfil the requirements, because it is a tedious work to figure out and fix all errors request by request.
HTTP status code |
400 (BAD REQUEST) |
type |
urn:problem:ValidationError |
title |
Request validation failed. |
details |
If not in a separate field, also in the details all Validation errors could be listed. |
instance |
A unique identifier to later correspond to the logs, to identify real problems with login. |
validationError |
A list of all errors that occurred during the validation. The list should contain the fieldname and the reason of each failure |
Business Exceptions
HTTP status code |
Depending on the reason of the exception. Default: 400 (BAD REQUEST) |
type |
An exception specific type. |
title |
Exception specific title |
details |
This is often the message of the underlying exception. |
instance |
A unique identifier to later correspond to the logs, to identify real problems with login. |
Technical Exceptions
HTTP status code |
500 (INTERNAL_SERVER_ERROR) For technical exceptions |
type |
An exception specific type. 'urn:problem:InternalServerError' could be the default. |
title |
Exception specific title. 'An internal server error occurred' could be the default. |
details |
Hide the concrete error details and display "An unexpected error has occurred! We apologize any inconvenience. Please try again later." |
instance |