[api] What is the proper REST response code for a valid request but an empty data?

4 Answers

I strongly oppose 404 in favour of 204 or 200 with empty data.

The request was received and properly processed - it did trigger application code on the server, thus one cannot really say that it was a client error and thus the whole class of client error codes (4xx) is not fitting.

More importantly, 404 can happen for a number of technical reasons. E.g. the application being temporarily deactivated or uninstalled on the server, proxy connection issues and whatnot. Therefore the client cannot distinguish between a 404 that means "empty result set" and a 404 that means "the service cannot be found, try again later".

This can be fatal: Imagine an accounting service in your company that lists all the employees that are due to an annual bonus. Unfortunately, the one time when it is called it returns a 404. Does that mean that no-one is due for a bonus, or that the application is currently down for a new deployment?

-> For applications that care about the quality of their data, 404 therefore is pretty much a no-go.

Also, many client frameworks respond to a 404 by throwing an exception with no further questions asked. This forces the client developer to catch that exception, to evaluate it, and then to decide based on that whether to log it as an error that is picked up by e.g. a monitoring component or whether to ignore it. That doesn't seem pretty to me either.

The only advantage of 404 over 204 is that it can return a response entity that may contain some information about why the requested resource was not found. But if that really is relevant, then one may also consider using a 200 OK response and design the system in a way that allows for error responses in the payload data. Alternatively, one could use the payload of the 404 response to return structured information to the caller. If he receives e.g. a html page instead of XML or JSON that he can parse, then that is a good indicator that something technical went wrong instead of a "no result" reply that may be valid from the caller's point of view. Or one could use a HTTP response header for that.

Still i would prefer a 204 or 200 with empty response though. That way the status of the technical execution of the request is separated from the logical result of the request. 2xx means "technical execution ok, this is the result, deal with it".

I think in most cases it should be left to the client to decide whether an empty result is acceptable or not. By returning 404 despite of a correct technical execution the client may decide to consider cases to be errors that simply are no errors.

Another quick analogy: Returning 404 for "no result found" is like throwing a DatabaseConnectionException if a SQL query returned no results. It can get the job done, but there are lots of possible technical causes that throw the same exception which then would be mistaken for a valid result.


For example you run a GET request for users/9 but there is no user with id #9. Which is the best response code?

  • 200 OK
  • 202 Accepted
  • 204 No Content
  • 400 Bad Request
  • 404 Not Found

If it's expected that the resource exists, but it might be empty, I would argue that it might be easier to just get a 200 OK with a representation that indicates that the thing is empty.

So I'd rather have /things return a 200 OK with {"Items": []} than a 204 with nothing at all, because in this way a collection with 0 items can be treated just the same as a collection with one or more item in it.

I'd just leave the 204 No Content for PUTs and DELETEs, where it might be the case that there really is no useful representation.

In the case that /thing/9 really doesn't exist, a 404 is appropriate.

At first, I thought a 204 would make sense, but after the discussions, I believe 404 is the only true correct response. Consider the following data:

Users: John, Peter

METHOD  URL                      STATUS  RESPONSE
GET     /users                   200     [John, Peter]
GET     /users/john              200     John
GET     /users/kyle              404     Not found
GET     /users/search?name=kyle` 200     []
DELETE  /users/john              204     No Content

Some background:

  1. the search returns an array, it just didn't have any matches but it has content: an empty array.

  2. 404 is of course best known for url's that aren't supported by the requested server, but a missing resource is in fact the same.
    Even though /users/:name is matched with users/kyle, the user Kyle is not available resource so a 404 still applies. It isn't a search query, it is a direct reference by a dynamic url, so 404 it is.

Anyway, my two cents :)

Encode the response content with a common enum that allows the client to switch on it and fork logic accordingly. I'm not sure how your client would distinguish the difference between a "data not found" 404 and a "web resource not found" 404? You don;t want someone to browse to userZ/9 and have the client wonder off as if the request was valid but there was no data returned.

To summarize or simplify,

2xx: Optional data: Well formed URI: Criteria is not part of URI: If the criteria is optional that can be specified in @RequestBody and @RequestParam should lead to 2xx. Example: filter by name / status

4xx: Expected data : Not well formed URI : Criteria is part of URI : If the criteria is mandatory that can only be specified in @PathVariable then it should lead to 4xx. Example: lookup by unique id.

Thus for the asked situation: "users/9" would be 4xx (possibly 404) But for "users?name=superman" should be 2xx (possibly 204)



api   http   rest