How to say a REST-ful NO?

We had an interesting discussion at work yesterday: for a REST api, what HTTP status code to return when
a resource does not exist - a 200 OK with an empty result, a 204 NO CONTENT or a 404 NOT FOUND ?

A lively discussion resulted in a flurry of ideas and only one near-fatality. We figured it all boiled down
to what the client is asking for.

(1) If the client is requesting for a resource, it is either found (200) or not found (404).

(2) If the client is searching for a resource and the query is valid, you either get results (200 with a collection) or you get no results (200 with an empty collection).

Here, the client receives a 200 in both outcomes, implying that the query was valid but nothing matching it was found. This is slightly better than returning a 204 because we might not want to send an empty response body that the client will have to handle differently (think NULL object pattern).

There’s an interesting offshoot to this. What do these (arguably same) requests do?

/dogs/991404NOTFOUND/dogs?id=991200OK

If we follow the logic discussed above, we’ll get a 400 for the first request and a 200 for the second.
This actually makes sense if you see the object-vs-query distinction.
Another view is that the second url should be redirected to the first (with a 3xx status). IMHO, that’s a bit inconsistent, i.e., what happens if you have more than one query parameter, i.e., /dogs?id=991&annoying=true?