402

I'm trying to figure out what the correct status code to return on different scenarios with a "REST-like" API that I'm working on. Let's say I have an end point that allows POST'ing purchases in JSON format. It looks like this:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

What should I return if the client sends me "sales_tax" (instead of the expected "tax"). Currently, I'm returning a 400. But, I've started questioning myself on this. Should I really be returning a 422? I mean, it's JSON (which is supported) and it's valid JSON, it's just doesn't contain all of the required fields.

kamaci
  • 65,625
  • 65
  • 210
  • 342
David S
  • 10,941
  • 10
  • 50
  • 91
  • 1
    possible duplicate of [REST: Mapping application errors to HTTP Status codes](http://stackoverflow.com/questions/2380554/rest-mapping-application-errors-to-http-status-codes) – Anirudh Ramanathan Apr 21 '13 at 17:29

9 Answers9

478

400 Bad Request would now seem to be the best HTTP/1.1 status code for your use case.

At the time of your question (and my original answer), RFC 7231 was not a thing; at which point I objected to 400 Bad Request because RFC 2616 said (with emphasis mine):

The request could not be understood by the server due to malformed syntax.

and the request you describe is syntactically valid JSON encased in syntactically valid HTTP, and thus the server has no issues with the syntax of the request.

However as pointed out by Lee Saferite in the comments, RFC 7231, which obsoletes RFC 2616, does not include that restriction:

The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).


However, prior to that re-wording (or if you want to quibble about RFC 7231 only being a proposed standard right now), 422 Unprocessable Entity does not seem an incorrect HTTP status code for your use case, because as the introduction to RFC 4918 says:

While the status codes provided by HTTP/1.1 are sufficient to describe most error conditions encountered by WebDAV methods, there are some errors that do not fall neatly into the existing categories. This specification defines extra status codes developed for WebDAV methods (Section 11)

And the description of 422 says:

The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions.

(Note the reference to syntax; I suspect 7231 partly obsoletes 4918 too)

This sounds exactly like your situation, but just in case there was any doubt, it goes on to say:

For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

(Replace "XML" with "JSON" and I think we can agree that's your situation)

Now, some will object that RFC 4918 is about "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)" and that you (presumably) are doing nothing involving WebDAV so shouldn't use things from it.

Given the choice between using an error code in the original standard that explicitly doesn't cover the situation, and one from an extension that describes the situation exactly, I would choose the latter.

Furthermore, RFC 4918 Section 21.4 refers to the IANA Hypertext Transfer Protocol (HTTP) Status Code Registry, where 422 can be found.

I propose that it is totally reasonable for an HTTP client or server to use any status code from that registry, so long as they do so correctly.


But as of HTTP/1.1, RFC 7231 has traction, so just use 400 Bad Request!

Kristian Glass
  • 33,669
  • 6
  • 39
  • 71
  • 1
    Pin.net uses 422 for validation like errors if you send the wrong or missing data even with valid JSON structure. But it also sends 400 if the processing of the credit card number failed, that is there wasn't enough money in the card, or there's a suspected fraud... etc. It's a bit weird, but the descriptions of 400 or 422 don't fit the credit card situation. Or maybe they all fall under "validation errors". – CMCDragonkai Jan 01 '14 at 09:30
  • you should use 422 only if you support WebDAV methods. – nemesisdesign Jan 14 '14 at 18:39
  • 8
    Your answer (422) makes sense to me. This is also what Rails ([respond_with](http://api.rubyonrails.org/classes/ActionController/Responder.html)) uses when a resource couldn't be processed because of validation errors. – Tyler Rick Apr 01 '14 at 16:31
  • I also agree with that answer, and I reached the same conclusion while browsing the different HTTP error codes. Is there some sort of consensus on this issue in the REST community though ? – Pierre Henry May 22 '14 at 09:30
  • 1
    422 is known and tracked code: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Subsequent standards will have in mind this code and it is possible in future have 422 in HTTP codes RFC with same semantic. Use it when you have needs. – gavenkoa Jul 04 '14 at 08:13
  • 12
    Note the use of 422 in non-WebDAV spec here: http://tools.ietf.org/html/rfc5789#section-2.2 – Andrey Shchekin Nov 25 '14 at 02:22
  • 4
    Just as an update, RFC 7231 has a different description for response code 400 that changes the semantics. – Lee Saferite Jul 01 '15 at 18:40
  • Only thing I don't (didn't) understand is what changed in RFC 7231 that makes you think it's the correct answer now. I actually just re-read it though and now I get it. This could be worded slightly better by putting the answer first and the older answer history after, but thanks for the info! – taco Aug 17 '15 at 19:14
  • 1
    i don't understand this answer probably because i'm weak in English or because i don't know what WebDav exactly is. can somebody please tell me is it safe to use 422? @KristianGlass says in the answer: `i would chose the latter`. and by latter he meas `422`. and at the bottom of the answer he says just use `400`. so which should i use in this kind of situation? `422` seems better. but the last line of this post, i don't get it. – asedsami Mar 28 '16 at 07:45
  • 6
    My apologies - I updated this answer to reflect the change in RFCs and lost some clarity; I'll try to refactor. It is almost certainly *safe* to use 422, but nowadays you *should* use 400. – Kristian Glass Mar 31 '16 at 14:30
  • Am I correct in inferring that the answer to the more general question "when to use 400 and when 422?" is: "use 400 when the request is _syntactically_ is malformed, use 422 when the request is _semantically_ malformed"? – Qqwy May 14 '17 at 19:00
  • 1
    @Qqwy Prior to RFC 7231 I would have nodded enthusiastically; now it feels like 400 is probably most appropriate for both – Kristian Glass May 15 '17 at 15:00
  • 1
    @KristianGlass So are there then any situations left in which 422 should be used over 400? – Qqwy May 17 '17 at 15:48
  • Inanc - I rolled back your edit because the double negative was very deliberate - I explicitly would not claim *correctness*, just lack of clear *incorrectness* – Kristian Glass Aug 21 '17 at 16:24
  • 3
    I still think the spec could be a lot clearer. The examples given in the are clear cases of the client doing something wrong. The OP's situation also falls into that category. However, there are cases like "I understand what you're asking, but I refuse to do it because there is some business rule against it" is not so clear cut. It's not exactly the client's fault, so a 403 might actually apply, per the same spec: "However, a request might be forbidden for reasons unrelated to the credentials". I'd prefer to have separate codes for permission related stuff vs "it cannot be done" though. – Thorarin Jul 04 '18 at 19:07
  • 2
    I think it's stupid that the standards were change to fit the current status code usage patterns. It's like changing REST principles by dropping PUT and DELETE and replacing them with POST, because people often use POST for Update/Delete operations. Bad request now tells you either YOU made request with wrong syntax or the SERVER decided to refuse your request for some reason. It is such a mix of concerns I don't even believe it! – GeorgiG Jul 09 '19 at 10:33
  • As far as I understand, in case of the missing required attributes the solution suggested here is to use 400 status code. But jersey bean validator in java returns 422 in this case which is widely accepted standard library. Please suggest. – Harpreet Jan 07 '20 at 14:21
  • Just let me get this straight, is `RFC 7231` the latest? If so, there is no mention of `422` in there so does that mean it's now obsolete? – IMB Apr 20 '20 at 08:35
  • No wonder everyone is confused. I am still confused. ;-) – BMiner Mar 10 '21 at 15:24
60

Case study: GitHub API

https://developer.github.com/v3/#client-errors

Maybe copying from well known APIs is a wise idea:

There are three possible types of client errors on API calls that receive request bodies:

Sending invalid JSON will result in a 400 Bad Request response.

HTTP/1.1 400 Bad Request
Content-Length: 35

{"message":"Problems parsing JSON"}

Sending the wrong type of JSON values will result in a 400 Bad Request response.

HTTP/1.1 400 Bad Request
Content-Length: 40

{"message":"Body should be a JSON object"}

Sending invalid fields will result in a 422 Unprocessable Entity response.

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Issue",
      "field": "title",
      "code": "missing_field"
    }
  ]
}
  • I think this is the correct and understandable answer. – LEMUEL ADANE Feb 20 '20 at 02:35
  • 3
    Can't upvote it more. Wish that more upvoted answers would refer to this one. The specs (RFC, IANA) epically failed to provide clear definitions and distinction between the two. So the answer boils down to best practices and GitHub gives us one. – Alex Klaus Apr 22 '20 at 11:29
  • 1
    This has to be the accepted answer. Also, the url provided in the answer does no longer work and takes you to homepage. The latest url is : https://docs.github.com/en/rest/overview/resources-in-the-rest-api#client-errors. – IllegalSkillsException May 03 '21 at 21:51
40

400 Bad Request is proper HTTP status code for your use case. The code is defined by HTTP/0.9-1.1 RFC.

The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.

http://tools.ietf.org/html/rfc2616#section-10.4.1

422 Unprocessable Entity is defined by RFC 4918 - WebDav. Note that there is slight difference in comparison to 400, see quoted text below.

This error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

To keep uniform interface you should use 422 only in a case of XML responses and you should also support all status codes defined by Webdav extension, not just 422.

http://tools.ietf.org/html/rfc4918#page-78

See also Mark Nottingham's post on status codes:

it’s a mistake to try to map each part of your application “deeply” into HTTP status codes; in most cases the level of granularity you want to be aiming for is much coarser. When in doubt, it’s OK to use the generic status codes 200 OK, 400 Bad Request and 500 Internal Service Error when there isn’t a better fit.

How to Think About HTTP Status Codes

Filip
  • 2,615
  • 1
  • 24
  • 35
  • 4
    422 code is part of IANA registry http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml so any IMHO have no sense. In any case Facebook and Twitter REST API reinvent own codes and don't use RFC/IANA standards. So you can do. – gavenkoa Jul 04 '14 at 08:08
  • 16
    Section 11 specifically states they are added to the entire spec and not just within the WebDav spec: `The following status codes are added to those defined in HTTP/1.1 [RFC2616].` – Steve Tauber Jul 28 '14 at 10:27
  • 8
    Just because the code is described as part of the WebDAV spec doesn't mean it's WebDAV-specific! Status codes are supposed to be generic. – treat your mods well Jul 31 '14 at 14:22
35

To reflect the status as of 2015:

Behaviorally both 400 and 422 response codes will be treated the same by clients and intermediaries, so it actually doesn't make a concrete difference which you use.

However I would expect to see 400 currently used more widely, and furthermore the clarifications that the HTTPbis spec provides make it the more appropriate of the two status codes:

  • The HTTPbis spec clarifies the intent of 400 to not be solely for syntax errors. The broader phrase "indicates that the server cannot or will not process the request due to something which is perceived to be a client error" is now used.
  • 422 is specifically a WebDAV extension, and is not referenced in RFC 2616 or in the newer HTTPbis specification.

For context, HTTPbis is a revision of the HTTP/1.1 spec that attempts to clarify areas that were unclear or inconsistent. Once it has reached approved status it will supersede RFC2616.

Ahsath
  • 270
  • 1
  • 5
  • 15
Tom Christie
  • 30,203
  • 6
  • 94
  • 79
  • 4
    Doesn't the 403 Forbidden might also be used for this context then? Quote: _The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it...If authentication credentials were provided in the request, the server considers them insufficient to grant access....However, a request might be forbidden for reasons unrelated to the credentials._ So it looks like 403 can be used to reject requests outside of authentication. – garbagecollector Aug 24 '15 at 22:19
  • 1
    @garbagecollector note that "rejected for reasons outside of _credentials_" != "rejected for reasons outside of _authentication_." There are lots of ways to authenticate someone without using credentials, specifically. – Knetic May 23 '17 at 17:52
  • @garbagecollector no, credentials means authentication ("who are you"), which would be 401 upon failure. Authorisation ("what can you do") would be 403 upon failure. Full explanation here: https://stackoverflow.com/a/6937030/137948 Neither apply to the OP's "missing fields" situation because the error would be the same regardless of which user attempted it. I agree 400 is the right answer. – Will Sheppard Aug 08 '17 at 15:19
17

There is no correct answer, since it depends on what the definition of "syntax" is for your request. The most important thing is that you:

  1. Use the response code(s) consistently
  2. Include as much additional information in the response body as you can to help the developer(s) using your API figure out what's going on.=

Before everyone jumps all over me for saying that there is no right or wrong answer here, let me explain a bit about how I came to the conclusion.

In this specific example, the OP's question is about a JSON request that contains a different key than expected. Now, the key name received is very similar, from a natural language standpoint, to the expected key, but it is, strictly, different, and hence not (usually) recognized by a machine as being equivalent.

As I said above, the deciding factor is what is meant by syntax. If the request was sent with a Content Type of application/json, then yes, the request is syntactically valid because it's valid JSON syntax, but not semantically valid, since it doesn't match what's expected. (assuming a strict definition of what makes the request in question semantically valid or not).

If, on the other hand, the request was sent with a more specific custom Content Type like application/vnd.mycorp.mydatatype+json that, perhaps, specifies exactly what fields are expected, then I would say that the request could easily be syntactically invalid, hence the 400 response.

In the case in question, since the key was wrong, not the value, there was a syntax error if there was a specification for what valid keys are. If there was no specification for valid keys, or the error was with a value, then it would be a semantic error.

cdeszaq
  • 29,170
  • 25
  • 111
  • 169
  • Very underrated answer - thanks for the well worded explanation. – puiu Jun 03 '16 at 14:14
  • Exactly my thoughts on the matter! I'm coming from XML SOAP background and concept of schema just got into my blood and JSON documents rather don't announce their schema. To me it's whether server "understands" the request or not. If server doesn't know what "sales_tax" is then it's simply 400: "I have no idea what you sent me but definitely not what I want.". – Aleksander Stelmaczonek Jul 06 '17 at 16:38
4

422 Unprocessable Entity Explained Updated: March 6, 2017

What Is 422 Unprocessable Entity?

A 422 status code occurs when a request is well-formed, however, due to semantic errors it is unable to be processed. This HTTP status was introduced in RFC 4918 and is more specifically geared toward HTTP extensions for Web Distributed Authoring and Versioning (WebDAV).

There is some controversy out there on whether or not developers should return a 400 vs 422 error to clients (more on the differences between both statuses below). However, in most cases, it is agreed upon that the 422 status should only be returned if you support WebDAV capabilities.

A word-for-word definition of the 422 status code taken from section 11.2 in RFC 4918 can be read below.

The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions.

The definition goes on to say:

For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.

400 vs 422 Status Codes

Bad request errors make use of the 400 status code and should be returned to the client if the request syntax is malformed, contains invalid request message framing, or has deceptive request routing. This status code may seem pretty similar to the 422 unprocessable entity status, however, one small piece of information that distinguishes them is the fact that the syntax of a request entity for a 422 error is correct whereas the syntax of a request that generates a 400 error is incorrect.

The use of the 422 status should be reserved only for very particular use-cases. In most other cases where a client error has occurred due to malformed syntax, the 400 Bad Request status should be used.

https://www.keycdn.com/support/422-unprocessable-entity/

Clojurevangelist
  • 503
  • 7
  • 10
1

Your case: HTTP 400 is the right status code for your case from REST perspective as its syntactically incorrect to send sales_tax instead of tax, though its a valid JSON. This is normally enforced by most of the server side frameworks when mapping the JSON to objects. However, there are some REST implementations that ignore new key in JSON object. In that case, a custom content-type specification to accept only valid fields can be enforced by server-side.

Ideal Scenario for 422:

In an ideal world, 422 is preferred and generally acceptable to send as response if the server understands the content type of the request entity and the syntax of the request entity is correct but was unable to process the data because its semantically erroneous.

Situations of 400 over 422:

Remember, the response code 422 is an extended HTTP (WebDAV) status code. There are still some HTTP clients / front-end libraries that aren't prepared to handle 422. For them, its as simple as "HTTP 422 is wrong, because it's not HTTP". From the service perspective, 400 isn't quite specific.

In enterprise architecture, the services are deployed mostly on service layers like SOA, IDM, etc. They typically serve multiple clients ranging from a very old native client to a latest HTTP clients. If one of the clients doesn't handle HTTP 422, the options are that asking the client to upgrade or change your response code to HTTP 400 for everyone. In my experience, this is very rare these days but still a possibility. So, a careful study of your architecture is always required before deciding on the HTTP response codes.

To handle situation like these, the service layers normally use versioning or setup configuration flag for strict HTTP conformance clients to send 400, and send 422 for the rest of them. That way they provide backwards compatibility support for existing consumers but at the same time provide the ability for the new clients to consume HTTP 422.


The latest update to RFC7321 says:

The 400 (Bad Request) status code indicates that the server cannot or
   will not process the request due to something that is perceived to be
   a client error (e.g., malformed request syntax, invalid request
   message framing, or deceptive request routing).

This confirms that servers can send HTTP 400 for invalid request. 400 doesn't refer only to syntax error anymore, however, 422 is still a genuine response provided the clients can handle it.

YuVi
  • 966
  • 7
  • 12
0

Firstly this is a very good question.

400 Bad Request - When a critical piece of information is missing from the request

e.g. The authorization header or content type header. Which is absolutely required by the server to understand the request. This can differ from server to server.

422 Unprocessable Entity - When the request body can't be parsed.

This is less severe than 400. The request has reached the server. The server has acknowledged the request has got the basic structure right. But the information in the request body can't be parsed or understood.

e.g. Content-Type: application/xml when request body is JSON.

Here's an article listing status codes and its use in REST APIs. https://metamug.com/article/status-codes-for-rest-api.php

  • 5
    422 means that the syntax is valid, but the contents are not. Sending JSON where XML is expected means that the syntax is wrong, so a 400 is the correct response in this case. – Dirk Nov 07 '18 at 10:18
  • 1
    Exactly as Dirk said 422 means syntactically valid request (can be parsed and understood) but semantically invalid – Jacek Obarymski Dec 12 '18 at 02:37
  • 400: when the request can't be processed because of invalid syntax (e.g. parsing error); 422: when the request can't be processed because of invalid data (e.g. validation error). – Kitanotori Aug 23 '19 at 05:20
  • Your example for 422 is not valid because by sending json with an application/xml media type, the body automatically is syntactically incorrect and the response should be 400. – manemarron Feb 28 '20 at 18:37
-17

You should actually return "200 OK" and in the response body include a message about what happened with the posted data. Then it's up to your application to understand the message.

The thing is, HTTP status codes are exactly that - HTTP status codes. And those are meant to have meaning only at the transportation layer, not at the application layer. The application layer should really never even know that HTTP is being used. If you switched your transportation layer from HTTP to Homing Pigeons, it should not affect your application layer in any way.

Let me give you a non-virtual example. Let's say you fall in love with a girl and she loves you back but her family moves to a completely different country. She gives you her new snail-mail address. Naturally, you decide to send her a love letter. So you write your letter, put it into an envelope, write her address on the envelope, put a stamp on it and send it. Now let's consider these scenarios

  1. You forgot to write a street name. You will receive an unopened letter back with a message written on it saying that the address is malformed. You screwed up the request and the receiving post office is unable to handle it. That's the equivalent of receiving "400 Bad Request".
  2. So you fix the address and send the letter again. But due to some bad luck you totaly misspelled the name of the street. You will get the letter back again with a message saying, that the address doesn't exist. That's the equivalent of receiving "404 Not Found".
  3. You fix the address again and this time you manage to write the address correctly. Your girl receives the letter and writes you back. It's the equivalent of receiving "200 OK". However, this does not mean that you will like what she wrote in her letter. It simply means that she received your message and has a response for you. Until you open the envelope and read her letter you cannot know whether she misses you dearly or wants to break up with you.

In short: Returning "200 OK" doesn't mean that the server app has good news for you. It only means that it has some news.

PS: The 422 status code has a meaning only in the context of WebDAV. If you're not working with WebDAV, then 422 has exactly the same standard meaning as any other non-standard code = which is none.

GoFree
  • 11
  • 2