REST: Mapping application errors to HTTP Status codes

25,549

Solution 1

RESTful use of HTTP means that you must keep the API uniform. This means that you cannot add domain specific methods (ala GET_STOCK_QUOTE) but it also means that you cannot add domain specific error codes (ala 499 Product Out Of Stock).

In fact, the HTTP client error codes are a good design check because if you design your resource semantics properly, the HTTP error code meanings will correctly express any errors. If you feel you need additional error codes, your resource design is likely wrong.

Jan

Solution 2

422 Unprocessable Entity is a useful error code for scenarios like this. See this question what http response code for rest service on put method when domain rules invalid for additional information.

Solution 3

GET /package/1234/next_checkpoint returns 400 Bad Request if "next_checkpoint" and 1234 are valid to ask for but next_checkpont here doesn't make sense...

This is the wrong way to think about that URI.

URIs are opaque, so observing that parts of it are 'valid' and others are not doesn't make any sense from a client perspective. Therefore you should 'just' return a 404 to the client, since the resource "package/1234/next_checkpoint" doesn't exist.

Solution 4

You should use 4xx series responses that best match your request when the client makes a mistake, though be careful to not use ones that are meant for specific headers or conditions. I tend to return a human-readable status message and either a plain-text version of the error as the response body or a structured error message, depending on application context.

Update: Upon further reading of the RFC, "procondition failed" is meant for the conditional headers, such as "if-none-match". I'd give a general 400 message for that instead.

Share:
25,549
conny
Author by

conny

I finally figured out why this gray area to the right of my profile page was not working. I assumed it was supposed to show a diagram of reputation or something. At some point I think I even submitted a bug report about it. Now instead it turns out, it was in fact working all the time - it was just not telling me about it! This gray, square area, was in fact trying, in it its own little non-intuitive way to tell me "-You have not entered anything in the About Me field on your profile". This text is inside of that area. #UsabilityFail #Nyan

Updated on March 06, 2020

Comments

  • conny
    conny about 4 years

    Is it to be considered good practice to reuse RFC HTTP Status codes like this, or should we be making up new ones that map exactly to our specific error reasons?

    We're designing a web service API around a couple of legacy applications.

    In addition to JSON/XML data structures in the Response Body, we aim to return HTTP Status Codes that make sense to web caches and developers.

    But how do you go about mapping different classes of errors onto appropriate HTTP Status codes? Everyone on the team agrees on the following:

    GET /package/1234 returns 404 Not Found if 1234 doesn't exist

    GET /package/1234/next_checkpoint returns 400 Bad Request if "next_checkpoint" and 1234 are valid to ask for but next_checkpont here doesn't make sense...

    and so on... but, in some cases, things needs to be more specific than just "400" - for example:

    POST /dispatch/?for_package=1234 returns 412 Precondition Failed if /dispatch and package 1234 both exist, BUT 1234 isn't ready for dispatch just yet.


    (Edit: Status codes in HTTP/1.1 and Status codes in WebDAV ext.)

  • Steve Pomeroy
    Steve Pomeroy about 14 years
    Really? All it says is, “The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.” It doesn't specify if the error is in HTTP or the application-layer bit of the request. A 500 Server Error is to non-specific for requests where the client sent incorrect data. I tend to think 500 errors as things that should never happen (programming errors and the like), while 4xx series as meaning "invalid input".
  • Darrel Miller
    Darrel Miller about 14 years
    400 series are for when the client made a mistake. 500 series are for when the server made a mistake. In these scenarios the server did not cause the error so 500 is not valid.
  • David Pfeffer
    David Pfeffer about 14 years
    The "syntax" the RFC is referring to is HTTP syntax. You're looking at the HTTP RFC; how can it possibly be talking about an application level syntax error for a lower OSI level construct? Server error is appropriate here because the server is the one who cannot continue. The client may be at fault from an application perspective, but from an HTTP perspective it is the server's fault that the conversation is not continuing.
  • Steve Pomeroy
    Steve Pomeroy about 14 years
    I'm not fully convinced that "syntax" means strictly HTTP syntax or the combined request syntax, including things like your request body. The RFC doesn't specify and the language is fairly nebulous. In practice, you'd really like to have some way of differentiating between requests that can't be fulfilled due to the server or due to an error on the client somehow. Using a 500 vs. 400 seems to make the most sense for these cases.
  • Steve Pomeroy
    Steve Pomeroy about 14 years
    A note regarding this, another SO thread that's relevant: stackoverflow.com/questions/1959947/…
  • David Pfeffer
    David Pfeffer about 14 years
    @Steve Pomeroy, you have to consider separation of layers. Would you send a TCP FIN+SYN because you didn't like an HTTP protocol transmission? In the same way, you wouldn't send an HTTP code indicating a client error when you don't like the application layer's decisions.
  • Steve Pomeroy
    Steve Pomeroy about 14 years
    Another thing to back up this perspective: the XCAP specification (RFC4825, and uses HTTP) uses 400 response codes when there's an XCAP client error.
  • Steve Pomeroy
    Steve Pomeroy about 14 years
    Webdav (rfc2518), too, uses 400 response codes when there is a bad request body.
  • Steve Pomeroy
    Steve Pomeroy about 14 years
    So, how do things like Webdav (which uses HTTP) get away with extending it? Is it simply because it isn't HTTP (even though it uses it)?
  • Steve Pomeroy
    Steve Pomeroy about 14 years
    @David Pfeffer, Yeah, but the HTTP RFC is more loose about what the status code definitions mean. Take a look at the RFCs I cited below which use the 400 status response for their application-layer errors. After all, if you say that all application-layer client errors are to be 500 series responses then there is no simple way to transmit your own application-layer client errors without making up a new 4xx series HTTP status code. Additionally, other 4xx series codes refer to non-syntactical client errors.
  • conny
    conny about 14 years
    Yeah - I looked at the WebDAV extensions but I consider them highly DAV-specific and something I would rather not "reuse"...
  • conny
    conny about 14 years
    Question is: HOW does one of the most common web servers get away with all these "substatus" codes when the RFC says "3DIGIT followed by space(s)"? support.microsoft.com/kb/943891
  • conny
    conny about 14 years
    This was kind of where the discussion in our office got stuck... Good to see your arguments though :)
  • Jan Algermissen
    Jan Algermissen about 14 years
    @Steve: WebDAV extensions are uniform. The apply to any resource. It is ok to extend HTTP but the semantics of any extension must make sense for any resource.
  • Jan Algermissen
    Jan Algermissen about 14 years
    @Conny: Microsoft's status codes are just plain wrong. HTTP does not allow them.
  • Jan Algermissen
    Jan Algermissen about 14 years
    @Conny: Keep in mind that WebDAV is not a specific application. It is an extension of HTTP's uniform interface. It makes a lot of sense to reuse some of these extensions (e.g 422) but some are simply breaking REST's constraints (all or PROP*) or HTTP itself (COPY, MOVE). Those I'd not reuse.
  • Jan Algermissen
    Jan Algermissen about 14 years
    Think about PATCH for example. That is a perfectly good extension of HTTP. Or the sometimes mentioned WATCH (or MONITOR) to do pubsub with HTTP: <code> WATCH /my/feed Reply-To: some.org/please/send/notification/here </code> Jan
  • Darrel Miller
    Darrel Miller about 14 years
    @David Pfeffer HTTP is an application level protocol. It's response codes are intended to be used by distributed applications to indicate application errors.
  • David Pfeffer
    David Pfeffer about 14 years
    @Darrel Miller: I understand that HTTP is really an application layer protocol, I'm just saying that its a protocol on top of which other things are layered. The OP should use his own error codes in the response rather than using HTTP codes.
  • Mike
    Mike about 14 years
    Pretty much the 'point' of RESTful HTTP is to provide/conform to the uniform mechanisms by which clients and servers should interact (i.e. there's nothing to add/layer on top). Applications that leverage HTTP in a RESTful way do not 'layer' on top of HTTP; they are (deliberately) constrained and governed by its architecture. Clients are driven in RESTful applications by exchanging (hypermedia) representations through (not on top of) HTTP.
  • Artem
    Artem almost 13 years
    All very nice, but how is a client to know if the payload of that 4xx is hypermedia they expect or the hypermedia of tomcat reporting that the URL wasn't defined?
  • wprl
    wprl almost 10 years
    PATCH is redundant; it solves a perceived problem with PUT that actually does not exist in RFC 2616.
  • Jan Algermissen
    Jan Algermissen almost 10 years
    Hi wprl, which problem is PATCH solving that actually does not exist?