There is an entire category of WTF rooted in not understanding what HTTP status codes mean. As a quick refresher, the basic pattern is:

  • 100: hey, I got a note
  • 200: everything is cool
  • 300: look over here
  • 400: the client screwed up
  • 418: I am a teapot
  • 500: the server screwed up

Inside those ranges, there are more specific codes that provide the details, but most WTF code can't even get that much right.

For example, Abner's co-worker came across this Ruby method:

# GET /users/unique/user_name?value=foo
# GET /users/unique/email?value=foo@bar.com
def unique
  unless request.format == 'application/json'
    head 401
    return
  else

  status = nil
  if ["user_name", "email"].include? params[:id].to_s
    User.exists?(params[:id] => params[:value]) ? status = 200 : status = 404
  else
    status = 500
  end

  render :json => {}, :status => status
end

The purpose of this method is not to check uniqueness, as the name implies, but simply to check if a username or an email address exists in our system. To that end, the very first thing wrong here is the comment- in these Rails routes, the method name is the last portion of the URL- it should be /users/user_name/unique?value=foo. Or, since they demand you submit only requests for JSON data, unique.json should technically be the last portion of the path.

Which let's start with their guard that clients only return JSON. They at least get in the right range- it is a 400 error, but they managed to pick arguably the worst one in that range- 401: Unauthorized tells the browser it needs to log in. The most correct error would be 415: Unsupported Media Type, but even a regular 400 would be better.

Well, we get past that, and then we check if the params[:id] field is either user_name or email. Which makes the comment above even less accurate, because clearly we need an id and a value field in the querystring. But assuming that the query contains one of those values as ID, we do a search in the database- is there a user where that ID field has the value requested. If they do, we return 200, and if they don't, we return 404.

Hey, that's all fine and acceptable. Arguably, a 204: No Content would be better, since the only thing the client cares about is the status code, but we're just being nit-picky.

It's when the request is bad that things go wrong: a 500 error. "Something went wrong serverside" is a bad choice to return when a request is malformed. And for Abner, this particular 500 error caused him plenty of trouble, as he ended up wasting half a day trying to understand why the server was failing- when the server wasn't failing at all.

And while there's an obvious fix here- return a better status code- you'll be shocked to learn that the JavaScript client-side code depended on this returning a 500 for its own error handling.