REST API Error Handling

When building a REST API via SpringBoot, it is important to return meaningful error messages to the calling client.


    "status": 404,
    "code": 40483,
    "message": "Oops! It looks like that file does not exist.",
    "developerMessage": "File resource for path /uploads/foobar.txt does not exist.  Please wait 10 minutes until the upload batch completes before checking again.",
    "moreInfo": ""

We’ll describe the properties next.


The status property is merely the same HTTP status code (integer) in the response header. This is a convenience mechanism: by including the status code in the body, any REST client that processes the error has one and only one place to look to fully understand the error: the error representation itself.  There is no need to check header values or other locations to understand the message.


The code property is an error code specific to your particular REST API. It is usually something that conveys information very specific to your problem domain.

This is convenient because of the limitation of having only 24 widely known general purpose HTTP error codes. By using your own codes, you can convey much more specific and richer reasons as to why something failed. Again, the more information that the API client can receive, the better.

In the example above, the code property has a value of 40483. While the general purpose “status”: 404 indicates that the requested resource was not found, perhaps there is an application-specific code of 40483 that indicates not only that the resource wasn’t found, but it wasn’t found due to the fact that it wasn’t yet uploaded to the server.

Granted, this particular ‘uploaded file’ example is somewhat contrived, but the key point here is that your API can convey a much richer set of error information if you leverage your own codes.

TIP:  If your application does not have a specific error code for a particular error, it can be a good idea to default the code value to be the same as the status value. This ensures that the client always sees a code value and does not need to perform ‘does this property exist?’ logic. This is cleaner/easier for API consumers, and that’s a good thing for adoption.


The message property is a nice human readable error message that can potentially be shown directly to an application end user (not a developer).  It should be friendly and easy to understand and convey a concise reason as to why the error occurred.  It should probaby not contain technical information.  Technical information should be in the developerMessage property instead (covered next).

Why is this useful?

If you have a REST API consumer (e.g. your customer), and that consumer wishes to relay the message value directly to the end user, they can do so.  This allows API consumers to write user interfaces and support their own end-users very quickly without much work on their end.  The more things you do to save them time and keep them happy using your API, the better.


The developerMessage property conveys any and all technical information that a developer calling your REST API might find useful.  This is where you might include exception messages, stack traces, or anything else that you think will help a developer.


The moreInfo property specifies a URL that anyone seeing the error message can click (or copy and paste) in a browser.  The target web page should describe the error condition fully, as well as potential solutions to help them resolve the error condition.

This is probably THE most important property of all because the target web page can be freely formatted to represent whatever information you wish.  You could have links to your support department, ‘get help now’ chat dialogs, or whatever else you think might be useful.  Show the developers love, and they’ll continue using your API.

When your Spring MVC REST Controllers throw an Exception, the RestExceptionHandler will:

  1. Convert the Exception into a RestError instance. The RestError implementation embodies all of the Rest Error Representation properties discussed previously in Part 1.
  2. Set the appropriate HTTP Response Status Code on the HTTP response based on the constructed RestError.
  3. Render the RestError representation to the HTTP Response body. By default, we render a JSON body just like Part 1’s example.

Read more: