Hi, I'm Aaron.

HTTP Statuses: The Bad Ones

I recently learned that Salesforce’s API does this for one of its response payloads:

// HTTP/1.1 200 OK
    "requestId": "524059b7-bf60-4fa6-9271-32aaf3479091",
    "resultMessages": [
            "resultType": "Operational",
            "resultClass": "Error",
            "resultCode": "CustomObjectNotFound",
            "message": "Failed to resolve the Custom Object from the provided ObjectReferenceIdentifier [Id: ed9b5f8e-ebb7-e711-8103-005056b37304, Key: ]."

(The key parts to look at are lines 1 (200 OK) and 8 (Not Found).)

400s (You messed up)

In part 1, we covered the status codes in the 200-300 range; the good ones. This article deals with “The Bad Ones”, the 400-series, also known as “You Messed Up”.

These statuses are for when your request wasn’t formed correctly or the server is unable to process your request because you didn’t ask in the right way. This one has a lot more utility and can help steer your user towards providing better input.

400 (Bad Request)

A 400 is simple: “Bad Stuff Happened.”

This means the user submitted a request that the server wasn’t able to correctly parse into an action. I typically see this when the user submits form data to a valid target, but their parameters are in a weird shape. It can also be used when the user is potentially submitting a malicious payload and the server is being polite in response.

In a similar way to a 200 being a universal “All good!” response, a 400 can be a catch-all.

401 (Unauthorized)

The 401 is one of two status codes around permissions.

This requires a bit of definition.

  • Authentication is when you identify yourself
  • Authorization is when your identity is assigned permissions in a system

So a 401 code is called “Unauthorized”, but really, it means “Unauthenticated”; the user hasn’t identified themselves and the resource they’re attempting to access requires authorization – but to authorize, you need an identify authenticated first.

For the user, this is remedied by logging in.

403 (Forbidden)

By contrast, a 403 is “Forbidden”, but this one is actually “Unauthorized.” The user has already weighed, measured, and found wanting.

For the user, this is… well, they can’t really do anything about it. Ask nicely, maybe?

404 (Not Found)

Here’s the one everyone knows and loves, the 404!

Your request was formed correctly, but the resource you’re looking for isn’t available. The important thing for this one is that the server doesn’t know whether or not the resource is intentionally missing, just that it’s missing.

The 404 status is a little different from the next one (410). Think of 404 as like if you called a mall’s customer service line and asked if your friend was there, giving customer service your friend’s name. They can tell you that can’t find your friend, but they wouldn’t really have any way of knowing if your friend was there and was now “Gone”, or if they hadn’t ever been there at all.

405 (Method Not Allowed)

This is a slick one that you can use if you are doing resourceful routing. If you aren’t familiar with REST, then this error message might be a little confusing.

What the error message means is that a user has tried to use an HTTP action verb (GET, PUT, PATCH, POST, or DELETE) on a URL that doesn’t support that action. In a RESTful resource, a url that looks like /articles/ can support different kinds of requests – if you send POST /articles/ {} that usually maps to creating a new resource. Sending GET /articles/ would probably retrieve a collection of the Article resource.

In that example, if the server was only prepared to handle GET /articles/ and not POST /articles/ {} then sending the latter would warrant a response of 405.

Note that if you’re going to send a 405 you’re required to also send an Allow header that lists the actions that are allowed for that resource. eg. Allow: GET, in that example.

410 (Gone)

The 410, by comparison, is when the server knows that something is gone. To extend the analogy above, it’s when you call the business where your friend works and they know that your friend’s “Gone” for the day.

Practically speaking, this is the response you want to send when you “take an article down” and want to stop getting inbound traffic from search engines. When the search engine spiders crawl your site, if they go to a page they thought existed, but you send back a 410, that informs the search engine to delete that from their index. A 404 response might penalize the link as being flaky, but may not delete it outright.

418 (I am a teapot)

Including this one here mainly for trivia, as it was an April Fool’s Joke, though it’s also an official header with an RFC (RFC 2324) and everything! This is the response you send back when your IoT coffee machine can’t brew coffee because it is, in fact, a Teapot.

420 (Enhance Your Calm)

Yes, the Cannabis reference in 420 is intentional. This is an unofficial response (as far as I know, there is no RFC documenting its official use) and I don’t think Twitter even uses it anymore. The contextual meaning, though, was as a response for when the client is making too many requests too rapidly, and so the server was throttling them.

Officially, you should use 429 (see below).

422 (Unprocessable Entity)

For those of you building APIs, you’ll want to know about 422. We usually use these in API responses, and it kind of sits at the intersection of 400 and 500. It’s like a 400 because the request can’t be processed, but the request isn’t malformed. It’s like a 500 because the response is ultimately useless to the client, except the server isn’t encountering an error. It means “I don’t know what to do with what you gave me, so …. here.”

One key difference here between a 422 and a 500 is that the 422 has not bailed and is still at the helm of the execution. So you have access to your in-memory objects like variables and other retrieved data. The typical response is just an empty hash with this status code.

429 (Too Many Requests)

This is the official way to respond when throttling. A 429 response indicates to a client that it is requesting too much. You can also send back a Retry-After header (with a parameter that is the number of seconds to wait) to tell the client how long to wait.