RESTful Error Handling
by Ethan Cerami
A major element of web services is planning for when things go wrong, and propagating error messages back to client applications. However, unlike SOAP, REST-based web services do not have a well-defined convention for returning error messages. In fact, after surveying a number of REST-based web services in the wild, there appear to be four different alternatives for handling errors. Below, I outline the four alternatives, and then provide my opinion on which option or combination of options is best.
Option 1: Stick to HTTP Error Codes
In this scenario, the web service propagates error messages via standard HTTP Error Codes. For example, assume we have the following URL:
This service expects a single parameter: id indicating a book ID. The service extracts the id parameter, does a database look-up and returns an XML representation of the specified book. If the URL specifies an invalid or obsolete id parameter, the service returns an HTTP 404 Not Found Error Code.
Option 2: Return an Empty Set
In this scenario, the web service always returns back an XML document which can have 0 or more subelements. If some error occurs, an XML document with zero elements is returned. The O'Reilly Meerkat news service currently uses this approach. For example, the following URL connects to Meerkat and requests all Linux related articles from the past two days, and formats the results in RSS 0.91:
Now, try specifying an invalid category. For example, set c =ten, like this:
In this case, Meerkat returns an RSS document with zero
item elements. This indicates that there are no matching results, but it does not indicate whether this is a valid category ID which contains no news items, or an invalid category ID.
Option 3: Use Extended HTTP Headers
In this scenario, the web service always returns an HTTP 200 OK Status Code, but specifies an application specific error code within a separate HTTP Header. The Distributed Annotation System (DAS) currently uses this alternative approach. For example, the following URL requests sequence data from Human Chromosome 1 from the Ensembl DAS Server:
Now, try issuing this request for Human Chromosome 30 (there is no human chromosome 30!):
If you click on the link above, you will see an empty page. However, if you have network sniffer, you can see the following HTTP response:
HTTP/1.1 200 OK
X-DAS-Server: DazzleServer/0.98 (20030508; BioJava 1.3)
X-DAS-Capabilities: dsn/1.0; dna/1.0; types/1.0;
stylesheet/1.0; features/1.0; encoding-dasgff/1.0;
encoding-xff/1.0; entry_points/1.0; error-segment/1.0;
unknown-segment/1.0; component/1.0; sequence/1.0
Date: Sun, 30 Nov 2003 21:02:13 GMT
As you can see, the DAS server has returned an HTTP 200 OK Status code and a required X-DAS-Status code. In this case, the code 403 refers to a DAS Specific error code: "Bad reference object (reference sequence unknown)".
Option 4: Return an XML Error Document
In this scenario, the web service always returns an HTTP Status Code of 200, but also includes an XML document containing an application specific error message. The XooMLe application currently uses this approach (XooMLe provides a RESTful API wrapper to the existing SOAP based Google API). For example, the Google API requires that you specify a valid developer token. If you specify an invalid token, XooMLe returns an XML error document. As the XooMLe documentation puts it, "If you do something wrong, XooMLe will tell you in a nice, tasty little XML-package." For example, try this URL:
The request does not include a Google developer token. Hence, XooMLe returns back the following XML document:
<?xml version="1.0" ?>
<errorString>Invalid Google API key supplied</errorString>
The Amazon.com web services API also follows this approach, and each returned XML document can specify an ErrorMsg element. For example, see the Amazon.com Dev-Lite Schema.
Best Practices for REST Error Handling
Assuming you are busy implementing a REST-based web service, which error handling option do you choose? I don't believe there are (yet) any best practices for REST error handling (for an overview of other best REST practices, see Paul Costello's REST presentation, in particular [Side 59].)
Nonetheless, here are my votes for most important criteria:
- Human Readable Error Messages: Part of the major appeal of REST based web services is that you can open any browser, type in the right URL, and see an immediate response -- no special tools needed. However, HTTP error codes do not always provide enough information. For example, if we take option 1 above, and request and invalid book ID, we get back a 404 Error Code. From the developer perspective, have we actually typed in the wrong host name, or an invalid book ID? It's not immediately clear. In Option 3 (DAS), we get back a blank page with no information. To view the actual error code, you need to run a network sniffer, or point your browser through a proxy. For all these reasons, I think Option 4 has a lot to offer. It significantly lowers the barrier for new developers, and enables all information related to a web service to be directly viewable within a web browser.
- Application Specific Errors: Option 1 has the disadvantage of not being directly viewable within a browser. It also has the additional disadvantage of mapping all HTTP error codes to application specific error codes. HTTP status codes are specific to document retrieval and posting, and these may not map directly to your application domain. For example, one of the DAS error codes relates to invalid genomic coordinates (sequence coordinate is out of bounds/invalid). What HTTP error code would we map to in this case?
- Machine Readable Error Codes: As a third criteria, error codes should be easily readable by other applications. For example, the XooMLe application returns back only human readable error messages, e.g. "Invalid Google API key supplied". An application parsing a XooMLe response would have to search for this specific error message, and this can be notoriously brittle -- for example, the XooMLe server might simply change the message to "Invalid Key Supplied". Error codes, such as those provided by DAS are important for programmatic control, and easy creation of exceptions. For example, if XooMLe returned a 1001 error code, a client application could do a quick lookup and immediately throw an InvalidKeyException.
Based on these three criteria, here's my vote for best error handling option:
- Use HTTP Status Codes for problems specifically related to HTTP, and not specifically related to your web service.
- When an error occurs, always return an XML document detailing the error.
- Make sure the XML error document contains both an error code, and a human readable error message. For example:
<?xml version="1.0" encoding="UTF-8" ?>
<error_msg>Invalid Google API key supplied</error_msg>
By following these three simple practices, you can make it significantly easier for others to interface with your service, and react when things go wrong. New developers can easily see valid and invalid requests via a simple web browser, and programs can easily (and more robustly) extract error codes and act appropriately.
What is the best option for propagating error messages from REST-based web services? Are there other options beyond the four described here?
404 is Resource Not Found
"we get back a 404 Error Code. From the developer perspective, have we actually typed in an invalid host name"
about option 1
It's perfectly possible to return a http error in the header, and a custom error message in the body. This is common practice for "custom 404 pages".
Important issue, poor coverage
This is an important topic, but respectfully, I don't think you gave it the attention it deserves.
RE: Important issue, poor coverage
Point well taken. I hadn't considered caching. And, differentiating HTTP errors from application errors is not a simple task. However, as a follow-up to your post, I wonder if you had any best practice suggestions of your own. Or, perhaps, it is hard to come up with one best practice, and it makes more sense to develop error handling on a case-by-case basis? Part of my reason for posting this was to stimulate debate on the topic, and I welcome any additional input you have. If others know of existing articles on this specific topic, please post links here too. Thanks.
HTTP is an application protocol
Your recommendations for error handling expose a common misconception about REST and the web in general; HTTP is an application protocol, not a transport protocol. This fact means that the HTTP status codes apply to your application; your application is not separate from HTTP in the sense that it needs its own set of error codes.
RE: HTTP is an application protocol
Thanks for your comments. I removed references to 204 and 401 codes in the article, and now only discuss the 404 Error Code. On the first comment I got re: this blog, I also changed "invalid" host name to "wrong" host name.
Status codes are important. Use them.
If you use "2xx" all the time, not only do you fail to provide the correct status codes for the request-response cycle but, as someone pointed out, you break caching and undermine the HTTP specification itself and make it impossible for clients to be sophisticated HTTP consumers.