Phil Parker

« All posts


 16 October 2014

REST 4XX Status Codes, Syntax and Semantics

The Hypertext Transfer Protocol rfc(2616) states:

Client Error 4xx: The 4xx class of status code is intended for cases in which the client seems to have erred.

Contractual Obligations

Let’s look at a couple of scenarios which illustrate what I see as an annoying gap in convention for how to handle this class of error.

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

Compared to (assuming the same GIVEN, AND)

The first example (where the username field name was misspelt) you could think of as a “psuedo-compile” error (e.g. it could be found through a sufficiently advanced static analysis tool). The second example (where the value did not meet some validation criteria) could only really be found at runtime. However both give the same status code.

404 Not Found The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent.

Compared to (assuming the same GIVEN, AND)

Again, the first example (where the resource type was misspelt) you know is wrong simply be inspecting the contract, but the second example you can’t know if it’s wrong without knowing the internal state of the provider. Again, the same status code is returned.

So the two examples above give us two distinct classes of “the client seems to have erred”

  1. Client did not meet the communicated (and “reasonably enforceable”) contract
  2. Client met the contract but provided illegal arguments

From a consumer point of view, the action they would have to take pretty different:

  1. Get the development team out of bed to go back and inspect the contract more closely
  2. Probably handled dynamically by the system (possibly propagating some sort of validation error back to a downstream system)

Disambiguation Options

So given the above what are the options.

Do Nothing

The first option (always!) is Do Nothing. You are obviously already including explanations for 4xx errors as per the spec:

Client Error 4xx: the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition

However, I find this unsatisfactory. It requires a level of inspection that shouldn’t be required for such a broad difference in context, response entities are harder to see in most network devices, logging frameworks and debug tools and there is no good convention for how to structure them.

Use Decimal places in status codes

As per Microsoft

I’m not really a big fan. Whilst it’s not explicitly against the spec as far as I can see, I think most people (and maybe protocol implementations!) expect status codes to be 3 digit integers NOT floats/strings .

Create your own status codes

Nginx, twitter and Spring Framework have all had a habit of doing in the past.

But it means there is no external reference point for the (unless you are a big-enough deal to get on the Wikipedia Page!)

Use existing status codes more consistently

So it turns out the existing 4XX codes are sufficient if (a) you are willing to think more carefully about what they actually mean and (b) you don’t mind resorting to some that came from the WebDav spec!

Contract failures:

“Dynamic/Runtime” failures:

Other useful 4xx codes:

The great thing about this approach is you get to use my favourite HTTP Status Dog

comments powered by Disqus