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!