Many developers use 4xx status codes to indicate things
like data validation errors or other things that are not
part of the HTTP transport.
You mean like a form validation error? Surely an invalid request is a bad request. No? Many developers use 4xx status codes to indicate things
like data validation errors or other things that are not
part of the HTTP transport.
You mean like a form validation error? Surely an invalid request is a bad request. No?Invalid to whom? Should a form submitted with a username that already exists in the system get a 500 response code? What's the server error?
Incidentally, the RFC for 409 makes it quite clear that this touches the application layer:
> Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the representation being PUT included changes to a resource that conflict with those made by an earlier (third-party) request, the origin server might use a 409 response to indicate that it can't complete the request. In this case, the response representation would likely contain information useful for merging the differences based on the revision history.
https://tools.ietf.org/html/rfc7231#section-6.5.8
In any case, getting pedantic about what's "an error" and using 200 OK for everything that didn't fail at the transport layer is a super frustrating experience regardless of whether or not it's semantically correct. Please don't do that to consumers of your API.
> using 200 OK for everything that didn't fail at the transport layer is a super frustrating experience regardless of whether or not it's semantically correct
The semantics of my application's protocol do not necessarily mirror the semantics of HTTP, nor are the descriptive statuses semantically similar, since most HTTP statuses are simply about transport (even though a few touch on the "application" of URIs as resources).
I would typically decide what my response code should be depending on what I think the response should be.
If a user tries to register a new account then a successful outcome would probably be a new user resource. If the user tries to register a username that already exists, I'd also probably go with 409 Conflict as the user is trying to create a resource that already exists.
Would it kill you to send back a 400 status code upon an error? Having to check for { isError: true } or something similar is obnoxious. I don't see the value gain of responding 200 OK when the operation was not successful.
Well, do you care about all the successful and unsuccessful aspects of TCP that underlie the connection? No, you just care that it was successful, allowing the HTTP request. Assuming that is successful, then your API "operation" can occur and return its result.
I would argue that most of the time, for any sufficiently large application, you'll need to use application specific status codes anyway (as you said), so why bother trying to be specific with the HTTP error codes? Certain client-side applications parse out if the response is a 2xx, 3xx, 4xx, or 5xx, and log it differently. At which point you just need one of them to trigger the different logging behavior.
The only special case I can think of is 401, which you need to send to trigger the basic authentication pop-up window for most browsers.
A big portion of the improper overloading of HTTP status codes comes from WebDAV status codes seeming appealing when in fact WebDAV is a very specific set of functionality that is not really analogous to the way most REST APIs work... notably WebDAV offers locking semantics.
HTTP is not a closed protocol. There will never be a single document defining all HTTP methods, status codes and such. Nothing in the definition of status code 422 makes it inapplicable to non-WebDAV applications. It is as much standard HTTP as status code 400 is (both are “proposed standards” in IETF terms).
I'm not arguing it is, it's an extension that adds specific semantics to accomplish a specific purpose.
But some developers look at WebDAV and see a lot of similarity with some of the application specific error conditions they are working with and decide that overloading HTTP status codes is a good idea, when it rarely is.
The confusion comes when the API developer tries to shoehorn all application specific errors into pre-existing HTTP status codes.
In most cases it is clearer to simply adopt a payload format that includes application specific error codes, so that the clarity of your API does not depend on its incidental similarity to pre-existing HTTP codes.
422 is a class of errors, not a catch-all for all similar scenarios one might encounter in building an API.
Absolutely. This is a common practice and there’s even a proposed standard for it (RFC 7807). But such a payload need not be sent with 200 (OK). It can refine the status code instead of overriding it.
True, this is sometimes possible when (coincidentally) one of the HTTP specs or extensions defines one of the codes in a way that feels similar enough.
The mistake is to assume that there is already a code for everything and that one does not need to define application specific error codes, which is what many API developers do.