541

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
Machavity
  • 30,841
  • 27
  • 92
  • 100
IMB
  • 15,163
  • 19
  • 82
  • 140
  • 38
    Hint: Did you find User 9? – Chris Pfohl Jul 31 '12 at 18:47
  • @ChristopherPfohl No, but 404 and 204 seems most applicable – IMB Jul 31 '12 at 18:48
  • 67
    Hint 2: So the user 9 was *not found*? – Tomasz Nurkiewicz Jul 31 '12 at 18:49
  • @TomaszNurkiewicz so 404? others say 204 – IMB Jul 31 '12 at 18:50
  • 32
    @IMB who is saying 204? "No Content" indicates that the entity you're looking for exists, but has no representation. For example if blog with id 15 has no comments, and you didn't want to return an empty list for blog number 15's comments: "/blog/15/comments" would return NoContent. On the other hand if blog 15 does exists, '404 Not Found' is more appropriate. – Chris Pfohl Jul 31 '12 at 19:50
  • @ChristopherPfohl There was an answer yesterday it was deleted now. Thanks. – IMB Aug 01 '12 at 03:31
  • @IMB Just added an answer with a link to a blog that explains it quite nicely. – Chris Pfohl Aug 01 '12 at 13:24
  • 17
    @Crisfole didn't you mean _". On the other hand if blog 15 does **not** exists, '404 Not Found' is more appropriate"_ – gdoron Dec 07 '15 at 09:02
  • 22
    I most certainly did @gdoron! :) Thanks. Sadly I'm approximately three years too late to edit that and fix. – Chris Pfohl Dec 07 '15 at 17:25
  • 2
    @IMB Honestly, the W3 http spec shows the correct answer is by Jens Wurm. Please, for the sake of all devs seeking these answers consider changing the selected answer. – user1567453 Oct 21 '17 at 22:53
  • 7
    204 for the question in the title. 404 for the question in the description. The Request-URI does NOT stop at 'users'. If '9' doesn't exist, but you return 204, you're saying 'users/9' was successfully processed, but contains no data, which is 100% wrong. 204 does NOT mean the 'users' endpoint was found but resource '9' wasn't. It means 'users/9' was not found. Could be either 'users' or '9' or any part of the URI before it. Nothing specifies that 404 doesn't include server-side code processing. It is a client error. Client requested a non-existing resource. – Gilbert Mar 27 '18 at 19:00
  • There is some ambiguity/conflict between the question title and the question body. A path-based resource `users/9` was shown as an example, but some of the better answers addressed the question in the broader context indicated by the title. – Brent Bradburn Aug 20 '19 at 00:56
  • Opinions differ on this topic and selecting *the correct answer* is like saying *religion x* is the one and only. I think the two highest rated answers (200/204 as well as 404) both have their right to exist. – Mobiletainment Feb 06 '20 at 18:41
  • @user1567453 would you happen to know _where_ in the W3 HTTP spec it says that? (I realize it is nearly 3 years on) – Shai Cohen Jul 07 '20 at 22:54
  • 1
    Does this answer your question? [Proper REST response for empty table?](https://stackoverflow.com/questions/13366730/proper-rest-response-for-empty-table) – Michael Freidgeim Jul 08 '21 at 22:31
  • 1
    I'm here in 2023 an there is still no indisputable solution. Why don't they just redefine the 404 error to 'bad URL' and give us a new error code for 'resource not found' or vice versa. – elano7 Mar 11 '23 at 19:10
  • Just my 2c worth, but my understanding is that the resource identifier isn't just the id. It's the entire URI. So 404 makes sense to me here. – backdesk Apr 05 '23 at 11:24

29 Answers29

514

I strongly oppose 404 in favour of 204 or 200 with empty data. Or at least one should use a response entity with the 404.

The request was received and properly processed - it did trigger application code on the server, the client might not have made any mistake, and thus the whole class of client error codes (4xx) may not be 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.

Sure, the 5xx error class exists for such cases, but in reality the affected middleware components often have no way to know that the error is on their side and then just assume that the error is on the client side, and then respond with a 404 instead of 500/503.

Therefore based on the status code alone the client cannot distinguish between a 404 that means "the thing you were looking for does not exist" and a 404 that means "something is seriously wrong, report this error to the ops team".

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 and the 404 is actually coming from the tomcat that it's supposed to be installed into, instead of from the application itself? These two scenarios yield the same status code, but they are fundamentally different in their meaning.

-> For applications that need to know that a requested resource positively does not exist instead of just being temporarily unaccessible, 404 without response entity 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 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 without response entity despite of a correct technical execution the client may decide to consider cases to be errors that simply are no errors.

Another perspective: From an operations point of view a 404 may be problematic. Since it can indicate a connectivity/middleware problem rather than a valid service response, i would not want a fluctuating number of "valid" 404s in my metrics/dashboards that might conceal genuine technical issues (e.g. a misconfigured proxy somewhere in the request routing) that should be investigated and fixed. This is further excarbated by some APIs even using 404 instead of 401/403 (e.g. gitlab does such a thing), to conceal the information that the request URI would have been valid but the request lacked authorization to access it. In this case too a 404 should be treated as a technical error and not as a valid "resource not found" result.

Edit: Wow, this has caused a lot of controversy. Here is another argument against 404: Strictly from a HTTP spec (RFC7231) point of view, 404 does not even mean that a resource does not exist. It only means that the server has no current representation of the requested resource available, and this even may be only temporary. So strictly by HTTP spec, 404 is inherently unreliable regarding the nonexistence of a requested thing. If you want to communicate that the requested thing positively does not exist, do not use 404.

Jens Wurm
  • 5,946
  • 1
  • 10
  • 6
  • 59
    **Technical** reasons for a 'not found' are also known as server errors. Those should be in the 500s. Specifically: "The service cannot be found" is `503 Service Unavailable`. – Chris Pfohl Jan 23 '15 at 16:40
  • 73
    The asker was also asking about a specific resource: a single user (not the `/users` route, but `/users/9`, i.e. "The user known as #9"), so your 'empty result set' comparison doesn't make sense. 404 means that the object doesn't exist. – Chris Pfohl Jan 23 '15 at 16:41
  • 6
    @Crisfole That is not really how all web servers fronting REST apis would deal with it. Many web servers are throwing 404s for URLs all the time even though there are usually backend applications responding to that URL. Maybe it's logical from a Web server perspective, but that makes 404 very unreliable for "reverse-proxied" REST api:s. – Petter Nordlander Mar 05 '15 at 12:31
  • 64
    404 simply indicates that the **resource** requested (in this case user number 9) was not found. It has nothing to do with whether or not application code was fired, it has nothing to do with whether or not a backend application responded. A web server is what the question was about, there was no mention of reverse proxying in the question. – Chris Pfohl Mar 17 '15 at 18:52
  • 10
    Yep, but the reason why the resource requested wasn't found usually matters from an ops perspective. Was it not found because it does not exist, or was it not found because the service was temporarily not available? A bland 404 hides that reason, and many client frameworks handle it rather ungracefully, as 4xx are defined as error response codes. if the absence of the resource is not an error but a valid situation, then i think 2xx would be more appropriate. – Jens Wurm Jun 19 '15 at 07:47
  • 3
    503 instead of 404 if the application is not deployed or stopped of course would be another solution to that situation, but that's not something that one can set in the application code. Instead it's an aspect of the behaviour of the server, which may be out of reach for the developer. In case of doubt i hence would assume the worst case that the server returns 404 if the application is unavailable. – Jens Wurm Jun 19 '15 at 07:53
  • 63
    The reasoning in this answer is terrifyingly wrong. – Kurt Spindler Jul 29 '15 at 17:38
  • 1
    if `/users/9` matches a route template, but user `9` is not found, it's likely because user `9` has been deleted - not with 100% certainty, but very likely, as the client wouldn't just randomly try an actual ID like `9` for no reason; in that case, how about issuing a 410 Gone, which "Indicates that the resource requested is no longer available and will not be available again". Perhaps this will mitigate the problem where the client throws on 404? Unless it throws on any 4xx, of course. What do you think? – mindplay.dk Jan 06 '16 at 13:23
  • 38
    404: the client was able to communicate with a given server, but the server could not find what was requested. Literally that: request received, it was fine and properly formatted (bad request 400), it was authenticated or public (unauthorized 401/ forbidden 403), no payment necessary (payment required 402), the request method was fine (method not allowed 405), the request accept can be satisfied (not acceptable 406). 200 Ok should be used when the user gets the resource. Empty is not a resource. 400 range is for client errors 500 range is for server errors In short: Your reasoning is off. – Derk-Jan Feb 10 '16 at 08:33
  • 4
    Just going to comment that your added example is even better example for why it should be an *error* code not a success code. 404 should *never* be used to indicate that a service is down. You have 503 Service Unavailable or 502 Bad Gateway to do that. – Chris Pfohl Nov 10 '16 at 16:06
  • 7
    OK, I've been trying to understand the reasoning behind this answer for two years now because I believe it to be blatantly wrong, but at least 58 people disagree with me. I think I agree with the answer for a *search* type endpoint, but *not* for an endpoint searching for a single record. Even your examples suggest this is what you're imagining. I think /that/ is what you're getting at. Can you clarify for me? – Chris Pfohl Dec 02 '16 at 15:22
  • 5
    Lots of good discussion here! I can see why 404 is appropriate for REST... but man it's a pain adding conditional statements to every list in the application I'm currently working on in order to handle 404s when no results are found. It'd just be easier in my situation to receive an empty list of entities and handle it the same way I do when results are found. Just like other apps like mysql for example return an empty data set instead of an error when no results are found... – Chris Apr 25 '17 at 07:39
  • 5
    In what way is requesting /users/9 different from requesting /favicon.ico? I suspect how you answer this question determines if you think "this answer is terrifyingly wrong". Answer: there is no difference. If /favicon.ico doesn't exist, you'd return 404 not found, hence you'd return the same thing if /users/9 doesn't exist. Also: @Crisfole mentioned "add a reason phrase other than not found"; this is kind of important and completely mitigates the issue with fat-fingering the route. – kayjtea Jun 05 '17 at 19:15
  • 2
    @Chris I hear you, but using the wrong status codes makes it *much* harder for consumers of your API to debug their code. See a 404? You know you either fat-fingered the route or that resource is not present. Also, you can handle the 404 case automatically: Did you get a 404 from your Ajax request, re-route or display your 404 page. The end. Having to handle it specially is a *good* thing because it forces you to make a decision in code about how to handle it. There's nothing preventing you from seeing the 404, creating an empty response and then rendering that. – Chris Pfohl Jun 07 '17 at 15:12
  • 6
    I completely agree with this answer. Every call to the API should return an object with the status message and avoid using HTTP status code as responses. Wrapping it into a JSON helps you to monitor your application, there is no such thing as a RESTful api alone in the world connected direct to the client. It will *always* be something in the middle, orchestrator, discovery service, authentication, authorization and so on... – Sebastian Mar 30 '18 at 18:39
  • 5
    Is RESTing a resource the same as HTTPing a resource? As a real-world comparison: if I send a letter to a library requesting a particular book, I would be surprised to get a return letter 'address unknown'. The library should not abuse the snail-mail-protocol for letting me know they cannot find the book. Instead, I would expect a letter back (equivalent to HTTP status 200) explaining the book was not found. A REST service is not identical to an HTTP service. A REST service uses an HTTP service. Status 404 means HTTP not found, not REST not found? – anneb Apr 11 '18 at 22:21
  • 2
    @anneb REST and HTTP are pretty much synonymous. From wikipedia "Fielding's dissertation explained the REST principles that were known as the 'HTTP Object Model' ... and were used in designing the HTTP 1.1 and Uniform Resource Identifiers (URI) standards". – Chris Pfohl Oct 12 '18 at 03:02
  • 1
    I strongly oppose having a strong position on this... as a front-end developer, I prefer to deal with an empty array and add my logic there than to deal with errors, but also understand how 404 makes more sense. Just my 0 cents. – Camilo Delvasto Nov 08 '18 at 21:14
  • 404 is the correct response if this resource is intended to be a ReSTful web service. That user does not exist. It is a client error. The client asked for user 9 but user 9 doens't exist. You can use json+problem details (https://tools.ietf.org/html/rfc7807) to return more information if there is a genuine reason to distinguish 404 from the server from some other 404 (whatever that could be - a broken caching proxy?) – Bruce Adams Nov 25 '18 at 00:51
  • 10
    There's another reason why `404` is correct and `204` is wrong: Consistency of status codes across different HTTP methods on the same resource. `PUT /users/9` and `DELETE /users/9` would already return `204` in case the user exists and was successfully updated or deleted. What should those return in case the user did not exist? So why should `GET /users/9` return `204` in case the user does _not_ exist? Makes no sense. – Christian Hujer Dec 26 '18 at 12:42
  • 2
    I ran into a controversion situation here in the company that I work for. We have a gateway API to centralize our web app requests to microservices. There are many microserves and a considerable amount of routes for which one of them. There was a situation where the team responsable for one of the microservice changed all empty responses from empty array and 204 code to 404 code. We had a serious conversation to get a common sense. In our case we took into consideration the fact that a route when is not found could also return 404 code, so then we decided to get back to 204 and empty array. – M. A. Cordeiro Jan 07 '19 at 11:01
  • There are other status codes(5xx) which should be used for given example and not 404, if the client application is unable to distinguish between 404 was URL was incorrect or the resource was not present then the client developer has not done the testing correctly. – Sachin Gorade Dec 04 '19 at 12:45
  • 5
    I haven't seen many comments from the operations PoV. When you are a developer or an operations team or an "infra" team, you want to know that a certain service is "doing well". A very often used metric here is the amount of `4xx` and `5xx` responses the service returns. There you cannot distinguish between `404-nothing-found-here-business-as-usual` and `404-something-really-wrong-never-gonna-work` responses. So from the observability perspective I am definitely in favor of *not* returning a `404`. Perhaps we need an RFC like @umberto-bar proposes: a new `2xx` status code exactly for this? – jubr Jun 25 '20 at 07:34
  • Suppose you want the file /index-foo.html. Browser do a request, server processes, find no such file. Should it answer with `200 OK`? `/user/id/9` is a resource, there is no user with id 9, so 404. You are mixing layers. – motobói Apr 16 '21 at 15:09
  • 3
    I am amazed at how many people are OK with muddling server HTTP codes with an application for data not found. Some things to keep in mind: Using a 404 for both data not found AND HTTP resource not found violates the Single Responsibility rule. When I react to a 404 as a developer, now I need to put exception handling into my code. Having data not found is not "exceptional" Let's say I handle the exception. Was it because the URL was wrong or because the data was not found. This causes a lot of extra coding work. – Richard Ruge Apr 16 '21 at 23:19
  • 7
    I am amazed at how many people don't understand REST principles and therefore think it is okay to return 2xx _when a resource is not found_. – Søren Boisen May 27 '21 at 11:23
  • 2
    @SørenBoisen Why does "no content" not indicate that the resource isn't there? – Jens Wurm May 28 '21 at 09:01
  • @RichardRuge you might not _like_ how HTTP is supposed to work, but that's a separate discussion from how the standard is defined. – Evert Jul 13 '21 at 17:41
  • @JensWurm "No content" means the resource exists but has... no content. Like, an empty file on disk? – Tomasz Pluskiewicz Jul 13 '21 at 20:05
  • 3
    @TomaszPluskiewicz I'd interprete that as "you were looking in a valid place, but there was nothing in it" The information that i was looking in a valid place is important for the interpretation of the result. Knowing that the file could be accessed but was empty is different than not being able to read from the file system at all because the volume got unmounted. A simple 404 does not allow this distinction. – Jens Wurm Jul 14 '21 at 09:19
  • 1
    Not a valid answer. Here is better: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses 404 Not Found The server can not find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 to hide the existence of a resource from an unauthorized client. This response code is probably the most famous one due to its frequent occurrence on the web. – Slipmp Sep 13 '21 at 21:39
  • @Slipmp "In an API, this can also mean that the endpoint is valid but the resource itself does not exist." -> I find it hard to reconcile that with the HTTP spec in rfc2616, which says: "The 4xx class of status code is intended for cases in which the client seems to have erred." IMHO the mozilla page describes it that way because it has become widespread practice, but that doesn't mean that that is the only way, nor the best way to do it. – Jens Wurm Sep 17 '21 at 08:42
  • If "the application is currently down for a new deployment", how can it respond with a 404? This answer is wrong on so many levels. – Vishal Shah May 06 '22 at 16:16
  • 2
    @VishalShah E.g. a tomcat that the web application would be deployed into would respond with 404 if the requested context path is currently unknown as the application is stopped. 404s being "injected" by middleware such as misconfigured proxies or servlet containers or application servers is one of my main arguments against using them to communicate true nonexistence of a resource. – Jens Wurm May 07 '22 at 20:26
406

TL;DR: Use 404

See This Blog. It explains it very well.

Summary of the blog's comments on 204:

  1. 204 No Content is not terribly useful as a response code for a browser (although according to the HTTP spec browsers do need to understand it as a 'don't change the view' response code).
  2. 204 No Content is however, very useful for ajax web services which may want to indicate success without having to return something. (Especially in cases like DELETE or POSTs that don't require feedback).

The answer, therefore, to your question is use 404 in your case. 204 is a specialized reponse code that you shouldn't often return to a browser in response to a GET.

The other response codes are even less appropriate than 204 and 404:

  1. 200 should be returned with the body of whatever you successfully fetched. Not appropriate when the entity you're fetching doesn't exist.
  2. 202 is used when the server has begun work on an object but the object isn't fully ready yet. Certainly not the case here. You haven't begun, nor will you begin, construction of user 9 in response to a GET request. That breaks all sorts of rules.
  3. 400 is used in response to a poorly formatted HTTP request (for instance malformed http headers, incorrectly ordered segments, etc). This will almost certainly be handled by whatever framework you're using. You shouldn't have to deal with this unless you're writing your own server from scratch. Edit: Newer RFCs now allow for 400 to be used for semantically invalid requests.

Wikipedia's description of the HTTP status codes are particularly helpful. You can also see the definitions in the HTTP/1.1 RFC2616 document at www.w3.org

Chris Pfohl
  • 18,220
  • 9
  • 68
  • 111
  • 13
    Note: response codes in the 200s indicate success. Response codes in the 400s indicate failure. The summary, points one and two, are about the `204` response code (No Content). – Chris Pfohl Sep 07 '12 at 17:42
  • 353
    -1 as I too strongly oppose 404 as a response to a *successful* call that has no records to return. As a developer dealing with an API for a non-web app, I have wasted hours of contacting the developers of the API to track down why the API endpoint I was calling didn't exist, when in fact it did, it just had no data to report. With regards to a 204 not being particularly useful to a browser, that is a bit like the tail wagging the dog as most uses of API endpoints in our universe of smart devices are not browser based and those that are likely use AJAX. Sorry to take points away though. – Matt Cashatt Sep 16 '16 at 16:13
  • 59
    @MatthewPatrickCashatt you're free to downvote as you please. I now finally understand *why* people are downvoting me, but the rationale is still wrong. When receiving a 404 it doesn't mean the route doesn't make sense, it means there is no resource at that location. Full stop. This is true if you're requesting `/badurl` or `/user/9` when such a user doesn't exist. A developer can help by adding a better reason phrase than 'Not Found', but is not required to. – Chris Pfohl Sep 16 '16 at 17:26
  • 5
    Also, if you ask for something that doesn't exist it's not *successful* by any definition of the word. – Chris Pfohl Sep 16 '16 at 17:30
  • 31
    @Crisfole I'm inclined to disagree (though not downvote, keep reading), based off of the [W3 definition of 404](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html), specifically `The server has not found anything matching the Request-URI`. The web/application server has in fact found an ACTION matching the Request-URI, though the db server has not. However, it also says `This status code is commonly used when [...] no other response is applicable`, so I think that validates its usage somewhat (even if I don't agree with/like it). – Daevin Nov 10 '16 at 18:48
  • 5
    @Crisfole To add on Matt's comment, here is an [interesting link](http://softwareengineering.stackexchange.com/questions/203492/when-to-use-http-status-code-404-in-an-api). A quote : *4xx codes Tell a UA it did something wrong, the request it constructed isn't proper and shouldn't try it again, without at least some modification.* 404 errors also trigger catch conditions in Node's request-promise which makes things burdensome to work with. – Standaa - Remember Monica Jan 27 '17 at 17:28
  • 5
    @Stanislasdrg Yes, and I'd argue the UA *did* do something wrong when they requested a non-existent resource. A well designed API will have a directory endpoint that can be used to verify it exists in advance. – Chris Pfohl Jan 27 '17 at 20:11
  • 6
    REST is about *resources* not actions. `GET /users/2` is a request for "User number two". Especially with a `GET` request the goal is *never* to perform *any* side effect (unless it's recording a view or similar). – Chris Pfohl Feb 10 '17 at 14:40
  • 2
    Do none of your APIs use error messages? Every API I write has error messages to explain problems. On 404 we say something along the lines of "No User exists with the given ID." Solves the problem plain and simple. No more developers confused about why they are getting 404, as anyone with a brain would check the response for error messages. – Mitch Talmadge Jul 30 '17 at 21:36
  • 5
    Lets say the request is for `/patient/allergies/56`, which is a reference to a penicillin allergy. Consider two scenarios (1) There's a mixup in an API change from `/patient/allergies/{id}` to `/patient/allergy/{id}` which isn't well communicated, or (2) There's a mixup with a DNS record, and the api request gets routed to a another non-API HTTP server. In both cases conflating application errors ("I don't recognise that id, but I recognised your request") with lower level protocol errors ("I don't recognise that URL") into a single response (404) would have a terrible result. – Adrian Baker Aug 09 '17 at 01:05
  • 1
    @AdrianBaker Status Codes are for developers and browsers. For developers you should be adding error messages via Reason Phrase or a chunk of text/json you return with explanations. For browers a 404 is perfectly reasonable in all those cases. A user isn't going to be able to do anything differently between the two anyway. If the browser gets a 404 at the page level, hopefully your application will render an 'Oops' page – Chris Pfohl Aug 09 '17 at 12:54
  • 21
    I don't think you're addressing the point I'm making : a 404 is dangerously confusing. Relying a caller checking a reason phrase or the body of the response means you're not trusting the status code, in which case it's not useful. – Adrian Baker Aug 10 '17 at 01:59
  • 4
    @Crisfole Actually, sometimes you want to render something different: when the request was successful but returned an empty response VS when the request was not successful. I.e. "This patient has no allergies" VS "Oops! That page can't be found." Thus, I think AdrianBaker has a point with separating concerns of the protocol and application layer. – Magne Nov 17 '17 at 09:36
  • 1
    All HTTP codes starting from 4** are classified as client errors. However, if a client requested `/users/9`, I do not see how it is a client side error. It is simply empty response as no data exists. Many standard libraries over http client will throw explicit exception for 4** http code which makes life of a developer painful. – Adi Jan 06 '19 at 12:09
  • @MitchTalmadge 1 it's efficient to use a URI error as a user not found error. 2 on a mobile device, looking at crash logs and symbolizing them or even downloading them is a waste of time, when it's a simple user not found. After URI's are developed it is expected they will always work, no one is going to want to work with an API that expects a developer to chase simple issues looking for a tiny amount of text on a crash log that isn't easy to obtain.For Ajax maybe, not for mobile devices. – Nick Turner Apr 01 '19 at 22:45
  • 1
    I'd err on the side of 200 with an empty list if your endpoint is "/users/8". If it were "/user/8" then I think a 404 would be justified. Rationale being that "/users/" implies you want to deal with a collection and the "8" is just a filter for that collection. Whether you just have "/users" or "/users/8", the response should be consistent. – Rikaelus Sep 17 '19 at 17:17
  • 4
    What Adrian Baker and many others here miss to distinguish is the existence of an abstract entity which was requested (if not found it is 404 - or 410 in some situations), and the existence of the application handler for that route, which will check the existence of that entity. You are confused because "but that route is good, I hit a handler, so this means it is not an error". But you should realize 404 is not a technical error, it is an application error to the client to say "I know what you mean, but there is no such thing as you requested!" – Darko Maksimovic Apr 06 '20 at 05:49
  • 2
    404 is simply too vague and anyone who's used API rest responses enough will tell you this. What didn't exist? The user? The endpoint? The server? The table or DB? Something else? A response with empty data is entirely valid, the data was found, it was empty – James Oct 23 '20 at 13:18
  • The HTTP spec specifically calls out the response message as the place to elaborate on the issue. You're attacking a straw man argument. – Chris Pfohl Oct 26 '20 at 13:58
  • 1
    @Darko Maksimovic - But the question remains: how does one differentiate between a 404 error where the URL was invalid or unreachable, vs no data being returned from a *valid* URL? HTTP error codes have been around for a heck of a lot longer than REST, and as noted (https://en.wikipedia.org/wiki/HTTP_404) a 404 is typically used to indicate "when a user attempts to follow a broken or dead link". – dcp Dec 08 '20 at 16:50
  • @Chris Pfohl - "The HTTP spec specifically calls out the response message as the place to elaborate on the issue" Can you show me in the spec where this is mentioned? I checked on the 404 error code but I do not see anything mentioned about using the response message to elaborate on the issue. https://tools.ietf.org/html/rfc2616#section-10.4.5 – dcp Dec 08 '20 at 16:56
  • https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#6.1.1 "The Status-Code is intended for use by automata and the Reason-Phrase is intended for the human user." – Chris Pfohl Dec 10 '20 at 13:17
  • 2
    I think the root cause of the debate is the distinction between "resource" in REST vs. "action" in frameworks. In the REST sense, URL `/users/9`, which means the details of the user #9, is a specific resource different than `/users/8`. If the user #9 does not exist then this resource, aka URL, does not exist (hence, the response code 404). If you don't know the user #9 does exist or not you should not call `/users/9` in the first place (hence, client error). A better approach would be a filter on `/users` resource something like `/users?id=9` and this could return HTTP 200 with an empty array. – MÇT Jan 04 '21 at 14:39
  • I think plainly saying "Use 404" is too simple, that's why people downvote. It really depends on what you want to do in the client side if the content cannot be found. E.g. in our application we have some filtering logic if the user selects an entity and we enrich the filter values with some data from the backend via REST, based on data of thse selected entity. If no data can be found, its a viable scenario and we do not care, which is NOT what 404 says. And I agree, that using error codes for actually successful calls can be irritating at least. – Loop Apr 12 '21 at 05:49
  • 1
    @Loop right, but that's in a _search_ context. The question specifically asks for searching for a single entity with a specific id: "...GET request for users/9 but there is no user with id #9". That's different from an search result with no results (which shoudl absolutely be a 200 with a JSON body that gives an empty resultset. – Chris Pfohl Apr 12 '21 at 14:13
  • Wrong. 404 (and all the 400 series messages) is an error. Many client libraries will respond to these as errors and break code execution, which is wrong. Requesting something from a database that doesn't exist is not an error (usually, and if it is, it's specialized business logic that falls on the client's responsibility to implement it.) It's also wrong to use 404 for various other reasons, but though I should add this as nobody else seems to be talking about it. – sovemp May 17 '21 at 19:46
  • Funny I just wanted to actually do exactly the same search (search for a user with ID) and came across this question. I had actually "solved" this question a while ago by myself and went through all of these discussions by myself. Now it seems like everyone here is going through the same philosophical journey. My take is that the protocol did not work this topic out well enough to provide a general solution. Instead we will have to deal by reaching a consensus on a per-API basis and manifesting how the respective API will behave through documentation (and behave consistently API-wide). – El Mac Jun 05 '21 at 21:33
  • 1
    I think there's a lot of comments in this thread about what they would like HTTP to be, but that's separate from what the standard dictates. If you are making a request for a 'thing' on the server, and that thing did not exist, the request is a failure and the correct status is 404. – Evert Jul 13 '21 at 17:31
  • 1
    HTTP does not infer any meaning on the server about 'what handles a specific URI / Route / Path'. If you don't like that your tools throw errors, that's on the tools but that fact doesn't alter the HTTP standard. – Evert Jul 13 '21 at 17:33
  • 1
    The only exception I can think of (that also causes confusion sometimes) is when people model a collection/list of things and that list is empty. Some people argue that's also a `404`, but an empty set !== a non existent set. – Evert Jul 13 '21 at 17:38
  • @James "A response with empty data is entirely valid, the data was found, it was empty" No, it is not. The data was **not** found. Hence, the only valid response is a 404. I really don't understand what's so difficult to understand or reason about this for those who disagree. The specs are clear. So are the cases in which this error code is returned. The fact that frameworks may or may not throw exceptions, which is an implementation detail, and one I've never cared about whichever way it is implemented, has little bearing on the specs' correctness. – Tom Lint May 23 '22 at 12:44
  • So.. to be clear I'm pro 404 in this case. But I'm curious in the counter argument, what are we returning when the uri can not be mapped to a valid handler? This is when I use a 400 Bad request. Client do not try this again it will not work. But if they do give me a route to a valid handler and that handler can not identify the SINGLE resource it was asked to serve - I use 404. – Simon Hooper Aug 22 '22 at 13:52
  • Its quite late to join the discussion but here i found a better answer with sound reasoning - https://softwareengineering.stackexchange.com/questions/358243/should-no-results-be-an-error-in-a-restful-response/358293#358293 – Prakash K Oct 15 '22 at 06:13
  • @PrakashK That question is asking about a search endpoint: "Find me a list of things that match my query". If you have nothing coming back that's a 200 and a payload containing an empty array. This question is a question about "User #9" which is a specific instance that _doesn't_ exist and "wasn't found" in the system. Thus a 404 is the only correct answer to this. The 500+ people who voted for the alternate answer are wrong and every backend application framework I've ever used agrees with my reasoning. – Chris Pfohl Sep 01 '23 at 19:38
129

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     /unknown-url-egaer       404     Not Found
GET     /users/kyle              404     User Not found
GET     /users?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.

  3. After suggestions in the comments, customizing the message of the 404 is another way of helping out the API consumer to even better distinguish between complete unknown routes and missing entities.

Anyway, my two cents :)

Justus Romijn
  • 15,699
  • 5
  • 51
  • 63
  • 17
    Throwing my weight behind this style for a REST API. No client should ask for /users/kyle unless it was told that resource would exist via a call to either /users or /users?name=kyle – Gary Barker Apr 10 '18 at 10:08
  • @GaryBarker But since that is "user input" in some sort, the API still has to handle it correctly. While you should prevent the 404 in YOUR client, you can't be guaranteed that it actually was checked in the first place. Designing the API should be done without considering the exact implementation of your client, especially in terms of checked user input. – RicoBrassers Aug 06 '18 at 13:24
  • 4
    This is the answer I most agree with. Perfect example of how I want APIs to work. @GaryBarker's comment is perfect too. It's an error when you look up something by ID and it doesn't exist. You should know that ID exists before making the call. Mostly because getting some 'successful' empty response just kicks the error further down the road, probably to some 'cannot read property name of undefined' when doing user.name or something. – Jamie Twells Jan 23 '19 at 13:15
  • What about a combination of the two. Assuming users have friends. /users/kyle/friends?name=fred. Kyle does not exist, so would this response be 404? Or would it be 200 because we dont exactly care about kyle, we only care about searching for his friends with name fred? – JSextonn Dec 04 '19 at 23:08
  • 3
    IMO that would yield a 404, as it is an invalid request: Kyle does not exist, so searching for his friends is also not possible. – Justus Romijn Dec 05 '19 at 18:57
  • 3
    *It isn't a search query, it is a direct reference by a dynamic url, so 404 it is.* This. – Piotr Dobrogost Nov 19 '20 at 22:20
  • 2
    @JustusRomijn I (of course) agree with you. I might add one more line that I believe is at the crux of the debate here: `GET /usrs/john 404 Not found`. A developer can't distinguish between a fat-fingered route and a missing person. Thus why I promote `GET /users/kyle 404 No such user` and `GET /usrs/john 404 Not found`. – Chris Pfohl Dec 10 '20 at 13:29
  • @ChrisPfohl adding that information in the response is very helpful for the consumer so I would promote that as well. – Justus Romijn Dec 16 '20 at 14:45
  • +1 for this post. - one small change I do tho is: "GET /unknown-url-egaer 404 Not Found " - I would return 400 bad request, assuming that there is not resource handler for that uri at all. – Simon Hooper Aug 22 '22 at 13:55
  • @SimonHooper a 400 bad request actually means there is something done wrong at client side, not fat-fingering an url: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400 – Justus Romijn Oct 11 '22 at 11:16
  • @JustusRomijn for a website I would agree with you and use 404 - there is no page at this address. For a web api, I would still favour 400. Your request is invalid and should not be re-attempted without modification. – Simon Hooper Apr 17 '23 at 12:13
32

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.

j0057
  • 912
  • 1
  • 10
  • 21
  • 1
    It sounds like you prefer to program against an API using a more abstracted form called RPC. Rather than access resources by following verbs closely and a resource based url such as `customers/1/addressbook`, the RPC way is to call an endpoint like `GetCustomerAddressBook` and either receive the data or essentially null and not have to worry so much about the complexities of HTTP. There's pros and cons to both. – The Muffin Man Dec 11 '16 at 20:10
  • 4
    @The Muffin Man, I'm not sure how you can pretend to know whether I prefer REST or RPC, nor why it is relevant to a discussion about which status code to return to an HTTP GET request. – j0057 Mar 03 '17 at 20:46
  • I had some horrid caching issues when using 204. Chrome would treat the request strangely and wouldn't show anything in the network and cached the previous result. Even with all the no-cache headers in the world. I agree with this answer, 200 seems to be the best with an empty array/object passed to the user. – Jack Jan 13 '18 at 00:20
  • For collections a HTTP 200 with `items: []` is expected, as the collection does exist but it's just empty. A 204 would be very confusing here, it's used with APIs which are not supposed to return any content. When requesting a single resource a HTTP 404 is appropriate. – nod Jan 20 '23 at 10:21
29

In previous projects, I've used 404. If there's no user 9, then the object was not found. Therefore 404 Not Found is appropriate.

For object exists, but there is no data, 204 No Content would be appropriate. I think in your case, the object does not exist though.

Max
  • 10,701
  • 2
  • 24
  • 48
20

There are two questions asked. One in the title and one in the example. I think this has partly led to the amount of dispute about which response is appropriate.

The question title asks about empty data. Empty data is still data but is not the same as no data. So this suggests requesting a result set, i.e. a list, perhaps from /users. If a list is empty it is still a list therefore a 204 (No Content) is most appropriate. You have just asked for a list of users and been provided with one, it just happens to have no content.

The example provided instead asks about a specific object, a user, /users/9. If user #9 is not found then no user object is returned. You asked for a specific resource (a user object) and were not given it because it was not found, so a 404 is appropriate.

I think the way to work this out is if you can use the response in the way you would expect without adding any conditional statement, then use a 204 otherwise use a 404.

In my examples I can iterate over an empty list without checking to see if it has content, but I can't display user object data on a null object without breaking something or adding a check to see if it is null.

You could of course return an object using the null object pattern if that suits your needs but that is a discussion for another thread.

Bluebox
  • 373
  • 2
  • 12
17

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)

Ashish Singh
  • 181
  • 1
  • 4
16

What the existing answers do not elaborate on is that it makes a difference whether you use path parameters or query parameters.

  • In case of path parameters, the parameter is part of the resource path. In case of /users/9, the response should be 404 because that resource was not found. /users/9 is the resource, and the result is unary, or an error, it doesn't exist. This is not a monad.
  • In case of query parameters, the parameter is not part of the resource path. In case of /users?id=9, the response should be 204 because the resource /users was found but it could not return any data. The resource /users exists and the result is n-ary, it exists even if it is empty. If id is unique, this is a monad.

Whether to use path parameters or query parameters depends on the use case. I prefer path parameters for mandatory, normative, or identifying arguments and query parameters for optional, non-normative, or attributing arguments (like paging, collation locale and stuff). In a REST API, I would use /users/9 not /users?id=9 especially because of the possible nesting to get "child records" like /users/9/ssh-keys/0 to get the first public ssh key or /users/9/address/2 to get the third postal address.

I prefer using 404. Here's why:

  • Calls for unary (1 result) and n-ary (n results) methods should not vary for no good reason. I like to have the same response codes if possible. The number of expected results is of course a difference, say, you expect the body to be an object (unary) or an array of objects (n-ary).
  • For n-ary, I would return an array, and in case there are not results, I would not return no set (no document), I would return an empty set (empty document, like empty array in JSON or empty element in XML). That is, it's still 200 but with zero records. There's no reason to put this information on the wire other than in the body.
  • 204 is like a void method. I would not use it for GET, only for POST, PUT, and DELETE. I make an exception in case of GET where the identifiers are query parameters not path parameters.
  • Not finding the record is like NoSuchElementException, ArrayIndexOutOfBoundsException or something like that, caused by the client using an id that doesn't exist, so, it's a client error.
  • From a code perspective, getting 204 means an additional branch in the code that could be avoided. It complicates client code, and in some cases it also complicates server code (depending on whether you use entity/model monads or plain entities/models; and I strongly recommend staying away from entity/model monads, it can lead to nasty bugs where because of the monad you think an operation is successful and return 200 or 204 when you should actually have returned something else).
  • Client code is easier to write and understand if 2xx means the server did what the client requested, and 4xx means the server didn't do what the client requested and it's the client's fault. Not giving the client the record that the client requested by id is the client's fault, because the client requested an id that doesn't exist.

Last but not least: Consistency

  • GET /users/9
  • PUT /users/9 and DELETE /users/9

PUT /users/9 and DELETE /users/9 already have to return 204 in case of successful update or deletion. So what should they return in case user 9 didn't exist? It makes no sense having the same situation presented as different status codes depending on the HTTP method used.

Besides, not a normative, but a cultural reason: If 204 is used for GET /users/9 next thing that will happen in the project is that somebody thinks returning 204 is good for n-ary methods. And that complicates client code, because instead of just checking for 2xx and then decoding the body, the client now has to specifically check for 204 and in that case skip decoding the body. Bud what does the client do instead? Create an empty array? Why not have that on the wire, then? If the client creates the empty array, 204 is a form of stupid compression. If the client uses null instead, a whole different can of worms is opened.

Christian Hujer
  • 17,035
  • 5
  • 40
  • 47
14

According to w3 post,

200 OK

The request has succeeded. The information returned with the response is dependent on the method used in the request

202 Accepted

The request has been accepted for processing, but the processing has not been completed.

204 No Content

The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation.

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

401 Unauthorized

The request requires user authentication. The response MUST include a WWW-Authenticate header field

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

Priyantha
  • 4,839
  • 6
  • 26
  • 46
  • 5
    The w3 post is about HTTP status codes. HTTP is not identical to REST. REST mostly but not necessarily uses HTTP as a transport protocol. 404 is an HTTP transport error code. If REST would be the same as HTTP, should it not be called HTTP? – anneb Apr 11 '18 at 22:59
  • 1
    @anneb As you said REST uses HTTP so this answer totally makes sense. REST is not HTTP, REST is not a protocol anyway. REST does not need to be identical (or same as HTTP) for this answer not to make sense. – Koray Tugay Aug 22 '19 at 19:17
  • @Koray Tugay: google search also uses http, so according to this answer google search should respond http status 404 if nothing matches the search? – anneb Aug 22 '19 at 23:36
  • @anneb Is Google Search you mention a RESTful application? I do not think so.. Hence the answer will be no. Steering back to the original question and this answer instead of falling into a rabbit hole.. If Google Search one day creates a RESTful API (or maybe it already has, I do not know) it may return `204 No Content` when it finds no results. Not `404`, it has a result for you, but it has no content.. – Koray Tugay Aug 23 '19 at 00:18
13

It is sad that something so simple and well defined became "opinion based" in this thread.

A HTTP server only knows of "entities", which is an abstraction for any content, be it a static web page, a list of search results, a list of other entities, a json description of something, a media file, etc etc.

Each such entity is expected to be identifiable by a unique URL, e.g.

  • /user/9 -- a single entity: a USER ID=9
  • /users -- a single entity: a LIST of all users
  • /media/x.mp3 -- a single entity: a media FILE called x.mp3
  • /search -- a single entity: a dynamic CONTENT based on query params

If a server finds a resource by the given URL, it does not matter what its contents are -- 2G of data, null, {}, [] -- as long as it exists, it will be 200. But if such entity is not known to the server, it is EXPECTED to return 404 "Not Found".

One confusion seems to be from developers who think if the application has a handler for a certain path shape, it should not be an error. In the eyes of the HTTP protocol it does not matter what happened in the internals of the server (ie. whether the default router responded or a handler for a specific path shape), as long as there is no matching entity on the server to the requested URL (that requested MP3 file, webpage, user object etc), which would return valid contents (empty or otherwise), it must be 404 (or 410 etc).

Another point of confusion seems to be around "no data" and "no entity". The former is about content of an entity, and the latter about its existence.

Example 1:

  • No data: /users returns 200 OK, body: [] because nobody registered yet
  • No entity: /users returns 404 because there is no path /users

Example 2:

  • No data: /user/9 returns return 200 OK, body: {}, because user ID=9 never entered his/her personal data
  • No entity: /user/9 returns 404 because there is no user ID=9

Example 3:

  • No data: /search?name=Joe returns 200 OK [], because there are no Joe's in the DB
  • No entity: /search?name=Joe returns 404 because there is no path /search
Darko Maksimovic
  • 1,155
  • 12
  • 14
9

After looking in question, you should not use 404 why?

Based on RFC 7231 the correct status code is 204

In the anwsers above I noticed 1 small missunderstanding:

1.- the resource is: /users

2.- /users/8 is not the resource, this is: the resource /users with route parameter 8, consumer maybe cannot notice it and does not know the difference, but publisher does and must know this!... so he must return an accurate response for consumers. period.

so:

Based on the RFC: 404 is incorrect because the resources /users is found, but the logic executed using the parameter 8 did not found any content to return as a response, so the correct answer is: 204

The main point here is: 404 not even the resource was found to process the internal logic

204 is a: I found the resource, the logic was executed but I did not found any data using your criteria given in the route parameter so I cant return anything to you. Im sorry, verify your criteria and call me again.

200: ok i found the resource, the logic was executed (even when Im not forced to return anything) take this and use it at your will.

205: (the best option of a GET response) I found the resource, the logic was executed, I have some content for you, use it well, oh by the way if your are going to share this in a view please refresh the view to display it.

Hope it helps.

Community
  • 1
  • 1
  • 2
    Where did you come up with the idea that the resource is `/users` and not `/users/8`? That is just so incorrect. Both of them *are* resources, both of them are represented by URIs (uniform **resource** identifiers). – ruohola Jan 02 '22 at 16:11
  • Your answer is incorrect. The "/users/8" is a resource and if there is no user identified with the id=8, or if the server does not want to disclose that the user exists, it's correct to return 404 NOT FOUND. – Alexandre V. Feb 03 '23 at 10:35
  • `/user/8` is definitely a resource. I much prefer the [documentation](https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design#organize-the-api-design-around-resources) microsoft wrote on this. They explain RESTful design as a way to structure your URI's for resources. `/users` being a collection and `/users/8` identifying an item. Both being resources. A collection returning 404, would mean that the collection does not exist. A query against a collection (say you add some filter) could result in 204 or emtpy array, or an array with a single item. – infroz May 03 '23 at 13:24
6

According to Microsoft: Controller action return types in ASP.NET Core web API, scroll down almost to the bottom, you find the following blurb about 404 relating to an object not found in the database. Here they suggest that a 404 is appropriate for Empty Data.

enter image description here

Bill Roberts
  • 1,127
  • 18
  • 30
5

TL;DR:

  • If no user is found at /users/9, you should return a 404.
  • If no user is found at /users?id=9, you should return a 204.

Long Version:

After reviewing my own usage of these status codes and the examples on this post, I would have to say that 404 is the appropriate response if User #9 was Not Found at the url of /users/9.

In my system today, our Application Insights logs are filled with hundreds of logged 404 errors that muddy up our logs all because we decided to return 404's when /users/9 had no correlating data. However, this does not mean our approach was incorrect when setting up our responses, rather, I would propose that it means our approach was incorrect when setting up our routing.

If you're expecting an endpoint to get a lot of traffic and are concerned about logging too many 404 errors, you should change your routing to fall in line with the status code you want, not force a status code to be inappropriately used.

We've since decided to make 2 changes to our code:

  1. Change our route to work by expecting /users?id=9
  2. Change our error code to 204 so that the 404's don't fill our AI logs.

At the end of the day, the architect of the API needs to understand how their API will be used and what kind of routing will be appropriate for that use case.

I believe that in the case of /users/9, the resource you are requesting is the user itself, User #9; you are asking the server to respond with an object identified as "9" that happens to exist in a path that has the word 'user' in it. If that object was not found, you should get a 404.

However, if you call /users?id=9, I feel that the resource you are requesting is the Users controller while also providing a bit more specificity so that it doesn't return a full list of all users. You are asking the server to respond with a specific user who can be identified by an ID number defined in the query string. Thusly, if no data was found, it makes sense to me that a 204 would be applicable because even if no data was found, the controller was.

The query string approach also accomplishes something that I think helps not only the API developers but also the client developers (especially junior developers or future developers who inherit this code, or code that makes calls to it):

It becomes immediately clear to anyone involved that 9 is an ID, not some arbitrary number. This point may seem moot in such a basic example, but consider a system that uses GUIDs as row ID's or allows you to get data by a person's name, or even a system that is returning info for specific ZIP/postal codes instead of row ID's. It would be useful for all developers involved if, at a glance, they knew whether that identifying parameter was a first, last, full name, or a ZIP/postal code instead of an ID.

Villanite
  • 83
  • 2
  • 7
  • I fully agree with you answer here. I wrote much the same but apparently it wasn't posted. Just like `/user/8` would yield an 404 `/users/9` should if no user 9 exist. `/users?id=8` would 200 (provided user 8 exists) and /users?id=9 would 204 Not Found just as `/users?Name=John` if a user with name "John" is missing. Much the same as an empty resource – theking2 Mar 16 '23 at 13:11
4

Twitter uses 404 with a custom error message like "No data found".

Ref: https://developer.twitter.com/en/docs/basics/response-codes.html

Jay
  • 9,189
  • 12
  • 56
  • 96
  • 2
    Microsoft Azure uses 404 as well, but custom error message aren't possible when responding to HEAD requests. https://learn.microsoft.com/en-us/rest/api/resources/resources/checkexistence – Mike Feb 06 '19 at 13:30
3

I'd say, neither is really appropriate. As has been said – e.g. by @anneb, I, too, think that part of the problems arises from using an HTTP response code to transport a status relating to a RESTful service. Anything the REST service has to say about its own processing should be transported by means of REST specific codes.

1

I'd argue that, if the HTTP server finds any service that is ready to answer a request it was sent, it should not respond with an HTTP 404 – in the end, something was found by the server – unless told so explicitly by the service that processes the request.

Let's assume for a moment the following URL: http://example.com/service/return/test.

  • Case A is that the server is “simply looking for the file on the file system“. If it is not present, 404 is correct. The same is true, if it asks some kind of service to deliver exactly this file and that service tells it that nothing of that name exists.
  • In case B, the server does not work with “real” files but actually the request is processed by some other service – e.g. some kind of templating system. Here, the server cannot make any claim about the existence of the resource as it knows nothing about it (unless told by the service handling it).

Without any response from the service explicitly requiring a different behaviour, the HTTP server can only say 3 things:

  • 503 if the service that is supposed to handle the request is not running or responding;
  • 200 otherwise as the HTTP server can actually satisfy the request – no matter what the service will say later;
  • 400 or 404 to indicate that there is no such service (as opposed to “exists but offline”) and nothing else was found.

2

To get back to the question at hand: I think the cleanest approach would be to not use an HTTP any response code at all other than said before. If the service is present and responding, the HTTP code should be 200. The response should contain the status the service returned in a separate header – here, the service can say

  • REST:EMPTY e.g. if it was asked to search for sth. and that research returned empty;
  • REST:NOT FOUND if it was asked specifically for sth. “ID-like” – be that a file name or a resource by ID or entry No. 24, etc. – and that specific resource was not found (usually, one specific resource was requested and not found);
  • REST:INVALID if any part of the request it was sent is not recognized by the service.

(note that I prefixed these with “REST:” on purpose to mark the fact that while these may have the same values or wording as do HTTP response codes, they are sth. completely different)

3

Let's get back to the URL above and inspect case B where service indicates to the HTTP server that it does not handle this request itself but passes it on to SERVICE. HTTP only serves out what it is handed back by SERVICE, it does not know anything about the return/test portion as that is handeled by SERVICE. If that service is running, HTTP should return 200 as it did indeed find something to handle the request.

The status returned by SERVICE (and which, as said above, would like to see in a separate header) depends on what action is actually expected:

  • if return/test asks for a specific resource: if it exists, return it with a status of REST:FOUND; if that resource does not exist, return REST:NOT FOUND; this could be extended to return REST:GONE if we know it once existed and will not return, and REST:MOVED if we know it has gone hollywood
  • if return/test is considered a search or filter-like operation: if the result set is empty, return an empty set in the type requested and a status of REST:EMPTY; a set of results in the type requested and a status of REST:SUCCESS
  • if return/test is not an operation recogized by SERVICE: return REST:ERROR if it is completely wrong (e.g. a typo like retrun/test), or REST:NOT IMPLEMENTED in case it is planned for later.

4

This distinction is a lot cleaner than mixing the two different things up. It will also make debugging easier and processing only slightly more complex, if at all.

  • If an HTTP 404 is returned, the server tells me, “I have no idea what you're talking about”. While the REST portion of my request might be perectly okay, I'm looking for par'Mach in all the wrong places.
  • On the other hand, HTTP 200 and REST:ERR tells me I got the service but did something wrong in my request to the service.
  • From HTTP 200 and REST:EMPTY, I know that I did nothing wrong – right server, the server found the service, right request to the service – but the search result is empty.

Summary

The problem and discussion arises from the fact that HTTP response codes are being used to denote the state of a service whose results are served by HTTP, or to denote sth. that is not in the scope of the HTTP server itself. Due to this discrepancy, the question cannot be answered and all opinions are subject to a lot of discussion.

The state of a request processed by a service and not the HTTP server REALLY SHOULD NOT (RFC 6919) be given by an HTTP response code. The HTTP code SHOULD (RFC 2119) only contain information the HTTP server can give from its own scope: namely, whether the service was found to process the request or not.

Instead, a different way SHOULD be used to tell a consumer about the state of the request to the service that is actually processing the request. My proposal is to do so via a specific header. Ideally, both the name of the header and its contents follow a standard that makes it easy for consumers to work with theses responses.

Community
  • 1
  • 1
dariok
  • 188
  • 3
  • 12
3

According to the RFC7231 - page59(https://www.rfc-editor.org/rfc/rfc7231#page-59) the definition of 404 status code response is:

6.5.4. 404 Not Found The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists. A 404 status code does not indicate whether this lack of representation is temporary or permanent; the 410 (Gone) status code is preferred over 404 if the origin server knows, presumably through some configurable means, that the condition is likely to be permanent. A 404 response is cacheable by default; i.e., unless otherwise indicated by the method definition or explicit cache controls (see Section 4.2.2 of [RFC7234]).

And the main thing that brings doubts is the definition of resource in the context above. According the same RFC(7231) the definition of resource is:

Resources: The target of an HTTP request is called a "resource". HTTP does not limit the nature of a resource; it merely defines an interface that might be used to interact with resources. Each resource is identified by a Uniform Resource Identifier (URI), as described in Section 2.7 of [RFC7230]. When a client constructs an HTTP/1.1 request message, it sends the target URI in one of various forms, as defined in (Section 5.3 of [RFC7230]). When a request is received, the server reconstructs an effective request URI for the target resource (Section 5.5 of [RFC7230]). One design goal of HTTP is to separate resource identification from request semantics, which is made possible by vesting the request semantics in the request method (Section 4) and a few request-modifying header fields (Section 5). If there is a conflict between the method semantics and any semantic implied by the URI itself, as described in Section 4.2.1, the method semantics take precedence.

So in my understand 404 status code should not be used on successful GET request with empty result.(example: a list with no result for specific filter)

Community
  • 1
  • 1
  • I agree with this assessment, but this was not what was asked. If you're asking for a list, and it's an empty list, then the empty list still exist. The question is, what about a single item? – Evert Jul 13 '21 at 17:43
3

Such things can be subjective and there are some interesting and various solid arguments on both sides. However [in my opinion] returning a 404 for missing data is not correct. Here's a simplified description to make this clear:

  • Request: Can I have some data please?
  • Resource (API endpoint): I'll get that request for you, here [sends a response of potential data]

Nothing broke, the endpoint was found, and the table and columns were found so the DB queried and data was "successfully" returned!

Now - whether that "successful response" has data or not does not matter, you asked for a response of "potential" data and that response with "potential" data was fulfilled. Null, empty etc is valid data.

200 just means whatever request we did was successful. I'm requesting data, nothing went wrong with HTTP/REST, and as data (albeit empty) was returned my "request for data" was successful.

Return a 200 and let the requester deal with empty data as each specific scenario warrants it!

Consider this example:

  • Request: Query "infractions" table with user ID 1234
  • Resource (API endpoint): Returns a response but data is empty

This data being empty is entirely valid. It means that user has no infractions. This is a 200 as it's all valid, as then I can do:

You have no infractions, have a blueberry muffin!

If you deem this a 404 what are you stating? The user's infractions couldn't be found? Now, grammatically that is correct, but it's just not correct in REST world were the success or failure is about the request. The "infraction" data for this user could be found successfully, there are zero infractions - a real number representing a valid state.


[Cheeky note..]

In your title, you're subconsciously agreeing that 200 is the correct response:

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


Here are some things to consider when choosing which status code to use, regardless of subjectivity and tricky choices:

  1. Consistency. If you use 404 for "no data" use it every time a response is returning no data.
  2. Don't use the same status for more than one meaning. If you return 404 when a resource was not found (eg API end point does not exist etc) then don't also use it for no data returned. This just makes dealing with responses a pain.
  3. Consider the context carefully. What is the "request"? What are you saying you are trying to achieve?
James
  • 4,644
  • 5
  • 37
  • 48
3

The answers in this thread (26 at the time of writing) perfectly illustrate how important it is for a developer to understand the semantics of the constructs they are working with.

Without this understanding it may not be obvious that response status codes are properties of a response and nothing else. These codes exist in the context of the response and their meaning outside of this context is undefined.

The response itself is the result of the request. The request operates on resources. Resources, requests, responses, and status codes are the constructs of the HTTP, and as far as HTTP is concerned:

HTTP provides a uniform interface for interacting with a resource (Section 2), regardless of its type, nature, or implementation, via the manipulation and transfer of representations (Section 3). Source.

In other words, the realm of the response status codes is limited by an interface which only cares about some target resources, and deals with messages used to interact with these resources. The server application logic is out of scope, the data you work with is also unimportant.

When HTTP is used it's always used with resources. The resources are ether transferred, or manipulated. In any case, unless we are in a quantum world, the resource either exists or it doesn't, there is no third state.

If an HTTP request is made to fetch (transfer) the representation of the resource (as in this question) and the resource doesn't exist, then the response result should indicate a failure with the corresponding 404 code. The objective - to fetch the representation - is not met, the resource was not found. There should be no other interpretation of the result in the context of the HTTP.

RFC 7231 Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content, was referred to multiple times here, but mainly as a reference for status code description. I would highly recommend to read through the whole document, and not only section #6, to get a better understanding of the scope and semantics of the HTTP interface and its components.

wombatonfire
  • 4,585
  • 28
  • 36
2

204 is more appropriate. Especially when you have a alert system to ensure you website is secure, 404 in this case would cause confusion because you don't know some 404 alerts is backend errors or normal requests but response empty.

sueaki
  • 45
  • 2
2

Just an addition from a developer that struggled many times with this situation. As you might have noticed it is always a discussion whether you return a 404 or 200 or 204 when a particular resource does not exist. The discussion above shows that this topic is pretty confusing and opinion based ( while there is a http-status-code standard existing ). I personally recommend, as it was not mentioned yet I guess, no matter how you decide DOCUMENT IT IN YOUR API-DEFINITION. Of course a client-side developer has in mind when he/she uses your particular "REST"- api to use his/her knowledge about Rest and expects that your api works this way. I guess you see the trap. Therefor I use a readme where I explicitly define in which cases I use which status code. This doesn't mean that I use some random definion. I always try to use the standard but to avoid such cases I document my usage. The client might think you are wrong in some specific cases but as it is documented, there is no need for additional discussions what saves time for you and the developer.

One sentence to the Ops question: 404 is a code that always comes in my mind when I think back about starting to develop backend-applications and I configured something wrong in my controller-route so that my Controller method is not called. With that in mind, I think if the request does reach your code in a Controller method, the client did a valid request and the request endpoint was found. So this is an indication not to use 404. If the db query returns not found, I return 200 but with an empty body.

FishingIsLife
  • 1,972
  • 3
  • 28
  • 51
2

According to w3, I believe in the following:

2xx:

This class of status code indicates that the client's request was successfully received, understood, and accepted.

4xx:

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

If a client requests for /users, and it has users to list, the response code would be 200 OK (the client request was valid).

If a client requests for /users and it has no data, the response code would still be 200 OK.
The entity/resource being requested is a list of users, the list exists, just without any users in it (a 204 No Content could be used if an empty response is given, although I think an empty list [] would be better).
The client request was valid, and the resource does exist, so a 4xx response code wouldn't make sense here.

On the other hand, if a client requests for /users/9, and that user does not exist, the client made a mistake by asking for a resource that does not exist, a user. In this case, it makes sense to answer with a 404 Not Found.

Bruno Kinast
  • 1,068
  • 4
  • 17
1

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.

ComeIn
  • 1,519
  • 17
  • 12
1

404 would be very confusing for any client if you return just because there is no data in response.

For me, Response Code 200 with an empty body is sufficient enough to understand that everything is perfect but there is no data matching the requirements.

darkenergy
  • 103
  • 11
  • That's not how the standard is defined or how the vast majority of HTTP applications works. – Evert Jul 13 '21 at 17:42
1

As stated by many, 404 is misleading and it doesn't allow the client to discriminate if the request uri doesn't exist, or if the requested uri cannot fetch the requested resource.

The 200 status is expected to contain resource data - so it is not the right choice. The 204 status means something else entirely and should not be used as response for GET requests.

All other existing status are not applicable, for one reason or the other.

I have seen this topic being discussed over and over in multiple places. For me, it is painfully obvious that to eliminate the confusion around the topic, a dedicated success status is needed. Something like "209 - No resource to display".

It will be a 2xx status because not finding an ID should not be considered a client error (if the clients knew everything which is in the server's DB, they would not need to ask anything to the server, wouldn't they?). This dedicated status will address all issues debated with using other statuses.

The only question is: how do I get RFC to accept this as a standard?

  • You start by writing a draft. I don't think this will get traction though. – Evert Jul 13 '21 at 22:21
  • You mentioned that "404 is misleading and it doesn't allow the client to discriminate if the request uri doesn't exist, or if the requested uri cannot fetch the requested resource." Answering: 404 is not misleading, it's crystal clear. The RFC 7231 states that "The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists.". If the server cannot fetch the resource for another reason, that is very likely one of the situations denoted by the status codes 5xx. – Alexandre V. Feb 03 '23 at 10:46
1

I dont think 404 is correct response.

If you use 404, how do you know it is that the api was not found or that the record in your database was not found?

From your description, I would use 200 OK since your api executed all logic without ANY issue. It just could not find the record in database. So, it is not API issue, nor database issue, it is your issue, you are thinking that the record exist but it does not. For that reason, API executed successfully, database query executed successfully, but nothing was found to return.

For that reason, in case like this, I would use

200 OK

with empty response like [] for arrays or {} for objects.

pixel
  • 9,653
  • 16
  • 82
  • 149
  • 2
    You might _prefer_ it, but it's not correct. – Evert Jul 13 '21 at 17:39
  • I appreciate your input @Evert. Assuming my Car object is represented as JSON ```{id, model, year}``` to make it simple, so just an JSON object with simple fields. Would you mind clarifying what should I get if I issue GET: /uri/to/cars/carid (/uri/to/cars/1) if car 1 does not exist? I mean both status and body that I should get back following proper practices? Much appreciated – pixel Jul 13 '21 at 21:16
  • 1
    You should at least emit a `404`, maybe a more specialized `410` and for the body I would suggest a common error format, such as RFC 7807. – Evert Jul 13 '21 at 22:19
  • @Evert I think the issue is that you are assuming users/9 is the URL. To me users is the URL and /9 is a parameter. You can't say that's wrong because 9 IS the parameter from the REST call. So in this case the users URL does exist and returning 404 would be wrong. Would you return a 404 for "users?id=9"? Ultimately this is a REST call over the top of HTML. Returning 404 to a REST client indicates the function call doesn't exist. If you wrap one tech inside another then the returned values should be appropriate to the outer layer, not based on the inner layer – MikeKulls Jul 01 '22 at 00:44
  • @MikeKulls it doesn't matter what the url is *to you*. What you wish the standards are like is irrelevant, and I won't discuss here what I think is better. HTTP has no concept of function calls, routes, etc. `/users/9` *is* the path component in the URL. – Evert Jul 01 '22 at 16:10
  • 1
    @Evert but end of the day this is a function called over the top of HTTP. In that function call the parameter is 9. Returning 404 would indicate the function doesn't exist when it does. Why stop at http? Http is built on TCP. Why not argue we should return TCP error codes? In this case I think the issue is the designers of REST have failed to add a layer here where HTTP error codes have been converted to valid REST error codes. End of the day return 404 is wrong because the function call does exist. – MikeKulls Jul 03 '22 at 01:02
  • @MikeKulls what designers of REST? There's no such thing as a REST error codes. REST is not a standard like HTTP or TCP. Read the dissertation, it doesn't take long! What I'm wondering is if you are trying to argue that I'm interpreting the HTTP standard incorrect, or if you arguing that the HTTP standard is wrong and we should not be following it for these cases. I'm only really interested in the first discussion. And for what it's worth, we _do_ use TCP error codes when things go wrong on the TCP layer! If we didn't the internet would be a mess. – Evert Jul 03 '22 at 03:18
  • @evert I'm not trying to argue about HTTP at all. I'm saying REST is a wrapper over the top of HTTP and hence the error codes returned should be based on REST and not HTTP. Basically based on what you expect for a function call and not what you expect for HTTP. Just like HTTP uses its own error codes and doesn't return TCP error codes. – MikeKulls Jul 03 '22 at 12:17
  • @MikeKulls what REST error codes are you referring to? Do you have an official source? – Evert Jul 03 '22 at 12:42
  • @Evert if there's no official standard then you're free to do what you want. For any wrapper you are certainly not constrained to use the error codes of the underlying technology. It's a function call, you should return expected values for a function call. If the designer of the function decides an empty response is valid then that up to them. – MikeKulls Jul 04 '22 at 07:48
1

What we have here is a tension between two paradigms.

In HTTP and REST, a URL identifies a resource, that user/9 resource includes the 9. HTTP should therefore return 404 - not found. This is the definition of RESTful. Later, you can PUT user/9, and then when you get then next time, you get the data. That's how HTTP and REST was designed.

An at HTTP level, if you didn't want a 404, a better URL would be user?id=9, then the user part would be found, and the function can do it's own processing and return it's own way of notifying "not found".

However, for convenience of specifying APIs, it's simply "much nicer" to use the user/9 format. This leaves us with the a dilemma: this request was made over HTTP, and the (opinionated) correct HTTP answer is 404; but through the lens of API consumers, the frameworks may not handle the 404 well, and they want a 200 + a "not found" payload (204 may also be problematic for many frameworks).

This layering an API on top of an already defined protocol (HTTP) is what has caused the tension. There's no problem when designed as a truely RESTful API (and correctly handling the 404's that that would produce).

If you believe that user/9 should return 200 + "not found", then you're using user as an RPC end point and then encoding parameters in the rest of the URL. I would suggest that this is poor design, contrary to a RESTful specification, and also totally understand how we got here.

If you control both ends - do what works, given the constraints of your server and - more likely - you client-side frameworks.

(Think of the consequences of doing a HEAD request on user/9 - you don't get to supply any content in the response. A 200 would indicate that user/9 does indeed exist, where as 404 would (correctly) indicate it's absence.)

dsz
  • 4,542
  • 39
  • 35
1

This are my notes on how I solve the situation:

  1. Error 404 is an old thing, when static pages were served. Therefore 404 not found means 'URL does not exist'
  2. I should get an error, not a success response when I call non existing user-id in /users/{user-id}. WHY: Because, I expect the user-id to exist, because, you never type the user-id, but usually you get it from a list of users (on a website) and click on it, which means it is expected to exist.
  3. BEST SOLUTION, BUT CURRENTLY NOT POSSIBLE (or possible if a company agrees upon it):
  • Use a new error code for artificial triggering of 'nothing found', for example 488 for 'resource not found', meaning: 'the function under the url could not find anything (on the server or in the database) and we raised an error because you were sure that something exists

  • The 404 will only be triggered automatically, by servers, if the URL is not proper. That is the common behavior of every server.

3.1) This would make understanding and debugging much easier, because:

  • 404 will tell you that your URL is bad and you did not even get to the server

  • On the other hand, 488 would for each search situation like /users/9 or /users?id=9 or /users + id_in_a_post_request_body tell you that the user, that you for some reason expected to exist, does not exist and you cannot continue your planned work (rendering 'user' a page).

  1. WORKAROUND (WITH CURRENT SITUATION):
  • if you do not find anything, raise error 404, but write a descriptive response message (do not use the default 'not found', but more like 'user not found')
elano7
  • 1,584
  • 1
  • 18
  • 18
0

Why not use 410? It suggests the requested resource no longer exists and the client is expected to never make a request for that resource, in your case users/9.

You can find more details about 410 here: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

akshat
  • 107
  • 8
  • 2
    'the client is expected to never make a request' - and what if that user gets created later, your answer suggest you could guarantee that this user will never exist, that's a very bold assumption and likely wrong – Holly Aug 23 '17 at 15:28
  • What Holly said. To add to her point: Even in case the user existed and got deleted, 410 is wrong, because what if the user gets undeleted? (Which kind of is a special case of gets created later.) – Christian Hujer Dec 26 '18 at 11:49
  • because 410 should be a permanent situation. https://www.restapitutorial.com/httpstatuscodes.html – Akostha Jan 24 '20 at 12:01
-2

In this scenario Ruby on Rails responses with 404 Not Found.

Client requested for a resource that does not exist. So, 404 Not Found is more appropriate.


Edit

I see that, in this scenario, many developer do not like 404 not found.

If you do not want to use 404, I think, you can use any of these two response codes:

  • 200 OK
  • 204 No Content

If you use 200 OK : response body should be empty json :[] or {}

If you use 204 OK : response body should be empty.

mahfuz
  • 2,728
  • 20
  • 18