Search code examples
expressresthttphttp-response-codes

HTTP code for an error in processing a request


Let's say we have an HTTP request made by the client. The endpoint exists and is accessible by the client (this rules out 401, 403, 404 and 405). The request payload is valid (this rules out 400). The server is alive and well, and is able to handle the request and return a response (this rules out 5xx).

The error arises within the processing of the request. Examples of such errors may include:

  • Business validation error.
  • Querying for an entity in a database that does not exist. Assume that the database lookup is only one part of the request processing pipeline (e.g. not the client request itself).
  • The server that handles the original client request makes an internal HTTP request that fails. In this case, the handling server is alive and well, while the internal HTTP request may return a 5xx. Assume that the internal HTTP request is only one part of the request processing pipeline (e.g. not the client request itself).

What is the appropriate HTTP code to assign for these responses?

I've seen API docs use 402 (Stripe) and 422 (PayPal), though I haven't come across anything definitive.

Thoughts from the community welcome!


Solution

  • What is the appropriate HTTP code to assign for these responses?

    Two important ideas

    First - your API is a facade, designed to make it look your service/business logic/etc is just another HTTP compliant document store (aka the "uniform interface" constraint). For the purposes of designing your responses, the specific nature of your resources and the implementation details are not significant.

    Second - the important point of a status code is how that status code will be understood by general purpose components (think browsers, web caches, reverse proxies, spiders...). We're trying to help these components broadly categorize the nature of the response. (This is one reason why there are relatively few codes in the 5xx class; there just isn't much that a general purpose component can do differently if the servers handling of the request fails).

    And here's the thing: the general purpose handling of two error status codes isn't significantly different. 403 Forbidden and 409 Conflict have different semantics associated with them, but the differences in the standardized handling of those codes, if any, are pretty subtle.

    You should make an effort to get 4xx vs 5xx right. It's often less important to precisely identify which 4xx code to use.


    Business validation error

    Common choices here would be 409 Conflict (your request is not consistent with my copy of the data), or 403 Forbidden (I understood your request, but I'm not going to fulfill it).

    If the problem is the data within the request itself (ie: somebody submitted the wrong form) you are more likely to see a 422 Unprocessable Entity (yes, I accept application/json, but not this application/json).


    Querying for an entity in a database that does not exist.

    The implementation details don't matter; can you trace the problem back to the HTTP request?

    If the problem traces back to the URI (we parse the target uri for some information, and use that information to lookup information in our data store), then 404 Not Found is often a good choice. If the problem traces back to the body of the request (we expected some option in the form to match an entry in our enumerated list, but it doesn't), then 409 Conflict is reasonable.

    If the server's data is flat out issing, then you are probably looking at a 500 Internal Server Error.


    The server that handles the original client request makes an internal HTTP request that fails.

    A failure of the server to connect to some other HTTP server is purely an implementation detail, like not being able to connect to a database or a file system.

    Unless that failure is a consequence of information in the request, you are going to end up with the 500 Internal Server Error.