49

I am working with a REST API which resides on a server that handles data for a multitude of IoT devices.

My task is to query the server using the API to collect specific performance information about said devices.

In one instance, I obtain a list of available devices and their corresponding identifiers, then later query the server for more details using those identifiers (GUIDs).

The server is returning a 500 Internal Server Error for a query on one of those IDs. In my application, an exception is thrown and I don't see details about the error. If I examine the response more closely with Postman, I can see that the server returned JSON in the body which contains:

errorMessage: "This ID does not exist".

Disregard the fact the server provided the ID to begin with -- that's a separate problem for the developer.

Should a REST API return a 500 Internal Server Error to report that a query references an object that doesn't exist? To my thinking, the HTTP response codes should refer strictly to the status of the REST call, rather than to the internal mechanics of the API. I would expect a 200 OK with the response containing the error and description, which would be proprietary to the API in question.


It occurs to me that there is a potential difference in expectation depending on how the REST call is structured.

Consider these examples:

  1. http://example.com/restapi/deviceinfo?id=123
  2. http://example.com/restapi/device/123/info

In the first case, the device ID is passed as a GET variable. A 404 or 500 would indicate that the path (/restapi/deviceinfo) is either not found or resulted in a server error.

In the second case, the device ID is part of the URL. I would be more understanding of a 404 Not Found, but still could argue based on which parts of the path are interpreted as variables versus endpoints.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
JYelton
  • 734
  • 1
  • 6
  • 12
  • Is this condition you're describing considered a success or a failure? – Robert Harvey Mar 23 '18 at 16:42
  • 3
    related (possibly a duplicate): [Should I return a 204 or a 404 response when a resource is not found?](https://softwareengineering.stackexchange.com/questions/322951/should-i-return-a-204-or-a-404-response-when-a-resource-is-not-found) – gnat Mar 23 '18 at 16:49
  • @RobertHarvey My expectation was that the API would return some information about the device. The query itself should have been a success, but the device ID having gone missing shouldn't cause a failure on the request level. – JYelton Mar 23 '18 at 17:47
  • The second example is already answered [here](https://softwareengineering.stackexchange.com/questions/364590/what-is-a-proper-response-status-code-to-post-when-parent-resource-is-not-found/364593#364593) – Dherik Mar 23 '18 at 18:28
  • Is there something that can be improved with the question, to whomever downvoted? – JYelton Mar 23 '18 at 18:36
  • Another related: https://stackoverflow.com/q/25378624/1531971 –  Mar 23 '18 at 19:37
  • 19
    An ID not existing sounds like a 404 to me. The most common reason for 500 errors is programmers allowing an internal exception to bubble up for the hosting server to handle. Sometimes there are truly exceptional cases where that happens and sometimes it's just lazy programming. Hard to say which is going on here. – Berin Loritsch Mar 23 '18 at 21:08
  • The fact that the server is running a query to retrieve results is an implementation detail transparent to the client. What if the server was storing everything on a file system and is just navigating to a path? Point is, client is saying "I want resource 123", I think it is appropriate for the server to say "I can't find resource 123, are you sure that's what you wanted?". The suggested alternative, return 200 with some string message, pushes a lot of unnecessary burden to the client. Now whenever you query for that resource, you have to handle both arbitrary string and valid representation. – FGreg Mar 23 '18 at 22:51
  • Incredible amount of viewpoints and insight came from asking this question. Thanks to everyone who has contributed, I have learned a lot. Ultimately it appears that while the server should not be returning a 500, it also shouldn't return a 200 (as I thought). – JYelton Mar 24 '18 at 00:16
  • Technically speaking, if changing ID can change resource then the first example is NOT REST. It's an HTTP API. Granted both example are HTTP APIs but only the second example is REST – slebetman Mar 24 '18 at 10:13
  • 11
    500 internal server means "It's our fault, we messed something up", and you should never *aim* to return this status to a user. Its purpose is to basically indicate a bug - your user can say they get a 500 when they make a particular request, and then you can go in and fix it. – berry120 Mar 24 '18 at 11:25
  • Possible duplicate of [Why is nesting or piggybacking errors within errors bad in general?](https://softwareengineering.stackexchange.com/questions/166964/why-is-nesting-or-piggybacking-errors-within-errors-bad-in-general) – Ferrybig Mar 25 '18 at 10:22
  • In contrast to what your question states, the answer does _not_ depend on the form of the URL. Receiving a certain status code on `http://example.com/restapi/deviceinfo?id=123` does _not_ mean that `http://example.com/restapi/deviceinfo` would have the same status code. They are different identifiers that point to different resources, despite their similar shape. – Ruben Verborgh Mar 26 '18 at 07:35
  • "In my application, an exception is thrown and I don't see details about the error." This worries me. Regardless of which error code the server returns, you should not lose valuable information. And just because you got the ID from the server previously, doesn't mean it's still valid. You HAVE to expect the ID to be invalid. – sbecker Mar 26 '18 at 08:18

11 Answers11

100

I think a 404 response is the best semantic match here, because the resource you were trying to find (as represented by the URI used for the query) was not found. Returning an error payload in the body is reasonable, but not required.

According to RFC 2616, the definition of the 404 status code is:

10.4.5 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. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.

FGreg
  • 105
  • 3
Andy Hunt
  • 5,996
  • 1
  • 33
  • 56
  • 6
    404 is only a semantic match if the id that doesn't exist corresponds to the resource that is being retrieved. – Robert Harvey Mar 23 '18 at 16:43
  • That's how I interpreted the OPs description, but yes I agree. – Andy Hunt Mar 23 '18 at 16:47
  • 1
    How do you differentiate between a 404 meaning "the query returned no results" and a 404 meaning "the endpoint does not exist"? I'm working with some APIs right now and this is a problem. – Thomas Owens Mar 23 '18 at 16:48
  • @ThomasOwens: Would "The endpoint does not exist" be worthy of a 500? – Robert Harvey Mar 23 '18 at 16:52
  • @RobertHarvey No. The endpoint not existing would be a 404. – Thomas Owens Mar 23 '18 at 17:06
  • 55
    @ThomasOwens A query returning no results would return 200 status and an empty array of results. A 404 would only be returned when specifying a specific object ID that does not actually exist. – Sean Burton Mar 23 '18 at 17:19
  • 3
    @SeanBurton I don't agree with that. Let's say you had an endpoint `/questions/368213` that did a SQL query something like `SELECT * FROM questions WHERE id = 368213` and there was no question with an ID of 368213. I would expect a 404 only if the endpoint `/questions/` does not exist. I would expect a 200 with a body indicating no results. – Thomas Owens Mar 23 '18 at 17:23
  • I have the same reaction to a `404 Not Found` as I do a `500 Internal Server Error` with regard to this API. To me, a 404 means that the endpoint doesn't exist. As in, `http://example.com/restapi/deviceinfo?id=123` is invalid. It would make me check the technical accuracy of the URL, not think that device 123 is absent. – JYelton Mar 23 '18 at 17:42
  • 12
    @ThomasOwens: from the caller's pespective, the endpoint isn't `/questions`, it's `/questions/368213`. That endpoint doesn't exist in your scenario. Think of it this way: if you do a GET on /foo/bar and there is no bar, why should the response be different if /foo exists or not? – Bryan Oakley Mar 23 '18 at 19:59
  • 5
    @JYelton: searching for and not finding something isn't a server error. The server is doing exactly what was requested of it. – Bryan Oakley Mar 23 '18 at 20:00
  • 17
    Right, it's not a server error so we don't send a 5xx. It's a client error - the client asked for something don't have, so we send 4xx, specifically 404. – bdsl Mar 23 '18 at 20:28
  • 7
    @ThomasOwens: `How do you differentiate between a 404 meaning "the query returned no results" and a 404 meaning "the endpoint does not exist"?` -- 400 Bad Request. – Robert Harvey Mar 23 '18 at 20:31
  • 3
    @RobertHarvey A bad request is when the request was bad. There's still a difference between a valid request that returns no data, an endpoint that doesn't exist, and a request that is invalid or malformed. – Thomas Owens Mar 23 '18 at 20:32
  • 3
    @ThomasOwens: A malformed URL *is* a bad request. A non-existent endpoint is essentially a malformed URL. I think you're asking a lot of the HTTP Error Codes system. By its own admission, it's necessarily incomplete, and at the end of the day, I'm not convinced that being precisely, semantically correct with these codes is all that useful (especially since the "proper" semantics are apparently debatable). – Robert Harvey Mar 23 '18 at 20:34
  • 2
    @RobertHarvey I'm thinking about it from a client's perspective. The codes are incomplete and imperfect. But there are a handful of important cases. Anyway, a malformed URL would be providing characters where a numeric ID is expected or XML instead of JSON or missing required fields in the body. Those are when you return a bad request. – Thomas Owens Mar 23 '18 at 20:37
  • 1
    Ultimately all I want is a way for my application to show useful information. I now have to assume that 4xx and 5xx codes _could_ mean that a device isn't checking in with the server, and the distinction between a typo in a URL and a missing device is fuzzy. – JYelton Mar 23 '18 at 20:37
  • @SeanBurton If we except your "200/404" premise in your highly upvoted comment... What then should happen for `example.com/rest/info?id=123&id=666` where 123 by itself would return 200 and 666 would return 404? I really think when you go through all the cases, Thomas is right that `info?id=666` should always return 200, even if it doesn't exist, because the endpoint does. – corsiKa Mar 24 '18 at 19:01
  • 1
    Id=666 is the endpoint. I'd expect a 404 too. A generic query that doesn't yield any results should return a 204 no content. – 9Rune5 Mar 25 '18 at 07:35
  • This is one of those rare times where I originally down-voted this answer because I disagreed that the API should return a 4xx code. After many comments and answers, I now see this as the most correct. Despite this, I cannot change the API and have to deal with it as-is, with its ill-placed 5xx codes. Thank you for the valuable input. – JYelton Mar 26 '18 at 01:05
  • 1
    @corsiKa: If you can specify multiple IDs to be returned in the same request, then that's a query; if it returns no results then it should return 2xx, just as SeanBurton said. I don't think you're disagreeing with him there! – psmears Mar 26 '18 at 16:04
  • @9Rune5 `id=666` is not an endpoint. `info` is an endpoint. Not every endpoint needs to be a resource. – corsiKa Mar 26 '18 at 16:18
  • 5xx is a server error - there's a bug in your server software that you should be fixing. – gnasher729 Jul 25 '19 at 20:05
  • Afaik the HTTP spec doesn't ever use or define the word "endpoint". It isn't meaningful to say "the endpoint doesn't exist". When people talk about endpoints it often refers to an internal implementation detail of the server. All you can meaningfully tell the client is whether the resource they requested exists or not. – bdsl May 12 '22 at 18:22
35

I will use your examples.

http://example.com/restapi/deviceinfo?id=123

If the endpoint returns a json array, the best choice for is 200 OK with a empty array if no result were found.

If the endpoint is designed to return a single result, my choice would be 404 NOT FOUND, because, for me, the right syntax for this kind of endpoint is: http://example.com/restapi/deviceinfo/123. I usually use request param only for filtering and when my endpoint returns an array.

http://example.com/restapi/device/123/info

I think this question was already answered here. POST or GET, the better choice seems 404 NOT FOUND because the resource 123 was not found.

In both cases I can't see the necessity to explain the reason of the request was not completed. The request information and HTTP code already explains why.

Thomas Owens
  • 79,623
  • 18
  • 192
  • 283
Dherik
  • 2,406
  • 20
  • 33
  • 2
    How do you distinguish between a nonexistent id and a bad URL? – Robert Harvey Mar 23 '18 at 20:22
  • Reiterating @RobertHarvey here, that's exactly my feeling. I am so used to seeing 404 with regard to things like mistakes in the URL that I spent lots of time looking for those types of mistake rather than thinking the server simply didn't find details on a database entry. – JYelton Mar 23 '18 at 20:26
  • @RobertHarvey I don't see problem to return **404** too, but it's also necessary in this case return more informations to describe the problem, like the `path` and a `message` attribute. Spring Framework does exactly this already. But I confess that I didn't like this on Spring in the first time that I saw this. If you are not comfortable to use 404, my choice would be **400**, that means something wrong with your request. Independent of your choice, I recommend to choose one and be consistent on your API. Sadly the HTTP codes cannot fulfill all the cases without some interposition among them. – Dherik Mar 23 '18 at 20:40
  • 1
    Following this reasoning, the API can also return 204 - No Content. In fact, I think it makes more sense a 204 than a 200 in this case. – luizfzs Mar 24 '18 at 11:32
  • 2
    @luizfzs, you can to that also, I can't see a problem on that. In some APIs that I developed, I prefer to use 204 in a successful PUT or DELETE ([as explained here](https://stackoverflow.com/a/2342589/2387977)) without any body on response. – Dherik Mar 24 '18 at 12:36
  • 10
    Why *should* you distinguish between a nonexistent id and a bad URL, at that level? Either way you're still making a valid request, as far as HTTP is concerned. The server just...well... *can't find* the resource you're addressing. A bad URL is not a malformed request; it's a well-formed request *for the wrong thing*. – cHao Mar 24 '18 at 16:47
  • 6
    @cHao Because as a developer, I want to know if my app is failing because the item doesn't exist, or if I accidentally pointed my app at app.company.cxm/test/ rather than app.company.cxm/tst/ – Patrick M Mar 24 '18 at 18:39
  • 7
    @PatrickM: As a developer, you should know that error responses can contain a message body too. That's where explanatory error info goes, if you really want it. Don't break semantics just because you're paranoid about fat fingers. At the HTTP level, it doesn't matter whether you messed up like `/itms/1234` or `/items/12234`. – cHao Mar 25 '18 at 02:38
  • [RFC 2606 § 3](https://tools.ietf.org/html/rfc2606#section-3) – TRiG Mar 25 '18 at 19:24
28

HTTP 404 is correct, because the server understands what resource the client is asking for, but it doesn't have that resource.

The fact that you're working with a "REST API" is the key. The API should behave like it's performing a REpresentational State Transfer, not executing a function. (Sure, the term "REST" has come to have a broader meaning, but you can still use its literal meaning to good effect here.) The client has asked for the state of a resource described by the URL http://example.com/restapi/device/123/info . A querystring (/deviceinfo?id=123) wouldn't change the situation. The server knows you're asking to transfer the state of device 123, but it doesn't recognize that as a known resource. Hence HTTP 404.

The other possible responses discussed here have specific meanings too:

  • HTTP 200 - We got the state for you; it's in the response body.
  • HTTP 204 - We got the state for you; it's blank.
  • HTTP 400 - We can't tell what resource you're asking about. Fix your URL.
  • HTTP 500 - We malfunctioned. Not your fault.

See RFC 2616 Sec. 10 as appropriate.

Thomas Owens
  • 79,623
  • 18
  • 192
  • 283
Travis Wilson
  • 445
  • 3
  • 3
  • I agree with your take on this. If the server was returning a 404, that would make more sense than what it's doing (a 500). Thank you. – JYelton Mar 24 '18 at 00:13
13

A 5xx error is typically used to indicate that the server encountered an error and cannot complete the request. If the server takes the request, can successfully parse it, and then does its work, that shouldn't return a 5xx error.

I'm unsure if there's any kind of convention on what to return if a query yields no results. I've seen both what you describe (a 200 with a body that contains a message) as well as a 404 indicating that results were not found. The 200 probably makes the most sense - the request successfully completed and there were no problems with the client's request or during the server processing the request. A body can deliver a message to the client.


I would treat both of your examples (http://example.com/restapi/deviceinfo?id=123 and http://example.com/restapi/device/123/info) the same - the 123 is a parameter. Both cases are different ways of structuring a request to get device information for a device with ID 123.

First, I would consider authorization and authentication. If the user does not have the appropriate permissions, I would return a 403 or a 401 as appropriate. Although it's called "Unauthorized", my understanding is that 401 is more about authentication and 403 is about unauthorized or permission denied. I wouldn't be too picky here, though, if you just wanted to stick to 403 for all authentication and authorization errors.

Then, I would handle the ID. Based on your example, it looks like it's a numeric ID. If a non-numeric value was provided, I would return a 400. If the parameter could possibly be a valid device identifier, then I would continue with processing. If there were other arguments, they would also be checked here. I would expect the response body to contain appropriate information about why the request was bad.

If all of the parameters were valid, I would begin to process the request. If the system or any dependency (a database, a third-party service, another internal service) is unavailable, I would return a 5xx code - 503 would be specific, but a 500 would also be acceptable. In either case, I would return a body with additional details. Do consider that if an external dependency reports a 408 Request Timeout, I would eat that and return a 500 to my client, allowing a client to receive a 408 only if the request to my system timed out. If the system is able to complete the request, I would return a 200 and the appropriate body.

204 may be useful in some cases, but it precludes you from sending a response body. Especially in an API setting, sending a response body with information that can be fed into a logging or reporting mechanism seems like the right decision to make in most cases.

The only time that a 404 would be returned is if the server did not have a /deviceinfo endpoint or a /device/:id/info endpoint.

I would not consider an ID that is not found to be the same as the resource not found. The resource is the device information for a particular device (in your example). Returning a 404 would mean that the resource (the device information) does not exist. A 200 with an appropriate body means that the system can indeed provide device information. There may or may not be a device with the specified ID.

Thomas Owens
  • 79,623
  • 18
  • 192
  • 283
  • You want to say "everything is fine" instead of "something bad happened?" – Robert Harvey Mar 23 '18 at 16:42
  • 1
    @RobertHarvey Yes. There were no errors. Just because the server generated the GUID and sent it to the client doesn't mean that another operation removed it. The request/response was successful. The command or query represented by the request did not return data. To me, that's not a failure. It *could* be an exception, but I'm not convinced that is worthy of a 5xx. – Thomas Owens Mar 23 '18 at 16:47
  • If there are no errors then the OP's question seems moot. – Robert Harvey Mar 23 '18 at 16:52
  • @RobertHarvey I don't understand why you'd say that. There are client-side errors (poorly formed or invalid requests). There are server-side errors (resources are unavailable or slow to respond). Then there are cases where everything completes but there is no data to send back - a query returns an empty set. This is that third case, from my understanding. – Thomas Owens Mar 23 '18 at 16:56
  • 204 No Content. – Robert Harvey Mar 23 '18 at 16:57
  • @RobertHarvey Per RFC 2616, a 204 cannot have a body in the response. The question is describing a JSON body being returned. If you want to return a JSON body, you cannot use a 204 and be compliant. A 200 with a body is still the most appropriate response, IMO. – Thomas Owens Mar 23 '18 at 17:18
  • 2
    If I were designing this API that I'm querying, I would have it return 200 with a body that then contains something to the effect of `device: 123; status: not found;`. Then I know the _query_ worked, and that the API is telling me useful information. – JYelton Mar 23 '18 at 17:51
  • @JYelton That's exactly what I believe the right thing to do is. – Thomas Owens Mar 23 '18 at 17:54
  • 1
    @JYelton I'll second TO's exactly. The implementation described in your question could be returning a 500 because it wasn't designed to handle the not-in-the-database case and throws an exception internally. – Blrfl Mar 23 '18 at 19:33
  • 7
    @Blrfl That is backed up (though not "proven") by the wording of a lot of websites 500 pages, usually something like "We made a mistake, and will investigate". In my mind a properly functioning server *never* sends 500s, except perhaps in the case of cosmic rays. – mbrig Mar 23 '18 at 19:52
  • @Blrfl: I think if the server returned a 500 because it wasn't designed to handle a not-in-the-database case, that's a bug that needs to be fixed. – Bryan Oakley Mar 23 '18 at 20:02
  • 6
    Http has no concept of an 'endpoint', no relevant distinction between a variable and the rest of the URL, and therefore neither does rest. You may have one a routing system that matches on a regex and routes thousands of URLs to one controller function, but that's an implementation detail, not a fundamental part of the API. A 200 response on a get is only for the case when the requested resource is being retrieved. In this case the client wants a representation of a resource that does not exist, so 404 is the correct response. – bdsl Mar 23 '18 at 20:02
  • 8
    A properly function *system* never sends a 500 response. A properly function *server* may send a 500 because if it is part of a larger system and it has detected an error internal to that larger system, e.g. database is down, or other depended on web service is returning nonsense results. – bdsl Mar 23 '18 at 20:07
6

A 500-series HTTP error indicates a server malfunction. Apart from 501 Not Implemented and 505 HTTP Version Not Supported, using these error codes carries the implication that retrying the request at a later time may succeed (although only 503 Service Unavailable explicitly states this). Ideally, a server should never produce one of these codes, although the inability to write bug-free software and provision the server with infinite resources means you'll need them from time to time.

For an "object does not exist" result, you should probably return either 404 Not Found (when the request is for an object by name), or 200 Success with an empty result body (when searching for an object by attributes). 204 No Content looks tempting, but I'd use it only for situations where a lack of a response body is the expected result.

Mark
  • 229
  • 2
  • 6
3

As a client of your API, when I make either of these calls:

  1. http://example.com/restapi/deviceinfo?id=123
  2. http://example.com/restapi/device/123/info

I expect to get back a (representation of) a DeviceInfo object (or some particular type anyway, whether that's a formal type or just something conforming to a documented "duck type" convention). I want a 200 status to mean I actually got one, and I can go ahead and use it.

For REST APIs, I think of 400 and 500 status codes as something like exceptions. You use them to indicate when you can't return a "normal" response for the request you've received, so the client will need to do something exceptional rather than process the information it was expecting to retrieve.

This means, as an API consumer, that I can use some sort of checked-rest-call function that retrieves a response or throws an exception. That's great; my normal logic can be straight line code, and I can organise my error-handling the same way I do in local code. Unexpected 404s will manifest as "no resource found" exceptions without me having to do anything at all, not as "missing attribute" errors when I'm later processing { errorMessage: "Device 123 not found" } as if it was a DeviceInfo object.

If you reason that the endpoint http://example.com/restapi/deviceinfo is found, and it's only the id=123 that isn't, and so return 200 with an error message in the body, then you're creating exactly the same kind of interface problems as C functions that could return either a correct result or an error code, or methods that indicate problems by arbitrarily returning null. It is much nicer as a user of your interface to have errors indicated through a "separate" channel from regular returns. That applies here too, even though HTTP 200, 404, and 500 responses are the same channel from a low level point of view. They're standardised and easy to tell apart so my REST client framework can easily switch on those statuses to turn them into the proper structures in my language; to do the same thing with the JSON layer (where you always say 200 and give me either a DeviceInfo or an error message) I need to embed some knowledge of the JSON schemas you use.

So only use 200 when you can return a valid value of the expected type (which is why http://example.com/restapi/search-devices?colour=blue can return 200 with an empty array if there are no blue devices; an empty array is a valid array, and a sensible answer to the request "I would like the details of all blue devices"). If you can't, use the most appropriate non-200 status code. Even though "device 123 does not exist" is the correct response to "give me the details of device 123", and is not an error for the server, it is an exception for the client's expectation that they'll get back a DeviceInfo and should not be communicated as a normal "here is what you asked for" response.

Ben
  • 1,017
  • 6
  • 10
  • Unfortunately I'm also a client of this API and can't change it. This is a great summary of how it _should_ work, though. – JYelton Mar 26 '18 at 01:03
0

You could use error 422 Unprocessable Entity to differentiate from 404 not found. 422 means that the server understand the request but it cannot give a proper response. I'm using this code on similar situations.

FiNeX
  • 117
  • 2
  • 4
    [This article](https://www.keycdn.com/support/422-unprocessable-entity/) describes using 422 in greater detail. I don't think this error code is really applicable here. – Robert Harvey Mar 23 '18 at 20:24
  • Thanks, very useful! I will have to deepen this subject! – FiNeX Mar 23 '18 at 22:55
0

Error 500 normally indicates that the request crashed a server side program; in enterprise environments these errors are treated as an egg in the face and are being avoided.

Error 4xx should signal to the programmer that the API endpoint (resource) does not exist. Consequently, once the appropriate endpoint is reached, any error handling from that point on is the API's programmer responsibility that should be handled gracefully, i.e. with an error message of a 200 response.

postronnim
  • 17
  • 1
0

Although the w3 notes that 404 is used when no other response is applicable, wouldn't this be what a 204 (No Content) response is good for? The request was valid from a processing standpoint and the server processed the request and has a result. That's a success, which leans towards 2xx responses. There was no content for this particular request so 204 tells the user that there was nothing wrong with their query but there's nothing there.

You could also make a weak case that 409 (Conflict) is an appropriate response. Though 409 is most often used for a POST, it does say

The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.

arguably the non existence of the requested id is the conflict here, and returning in the message that no such id exists in the system is enough information to the user to recognize and fix the conflict.

moneyt
  • 137
  • 4
  • 3
    No, 204 response on a gets request would only make sense when the requested resource has been found, and its representation is exactly zero characters long. – bdsl Mar 24 '18 at 23:12
0

The other answers cover it, but I just wanted to point out that a 500-series error means "I messed up." In this case, "I" means the API, so an unhandled server error or similar. A 400-series error means "you messed up" -- the caller of the API sent something incorrect.

Marcie
  • 3,009
  • 2
  • 19
  • 21
-4

Other users have provided valid answers for what to do if you want to go by the book.

However I would suggest that you are reading too much into the RESTfulness and being absolutely kosher with respect to it.

REST is a capricious protocol, because if you want to go by the book while using it, then it forces both client and server to be built having specific knowledge of the fact that they are communicating via REST, so in essence the specific communication protocol being used cannot be abstracted out.

There is a different approach: completely eschew RESTfulness, and use it just as a communication protocol and nothing else. This means that the only responses that need to be returned are "HTTP 200 OK" and "HTTP 500 Internal Server Error" because as far as the communication protocol is concerned, any attempt to communicate can only have two outcomes: either the request was successfully delivered to the server, or not.

What happens after delivery, is none of the communication protocol's business. So, once the server has successfully received the request, and begins processing it, many errors may occur, but these are all application-specific errors that are none of the communication protocol's business to know anything about. They should be communicated within the payload of a response that looks perfectly successful as far as the communication protocol knows.

So, bottom line is, I would recommend returning an "HTTP 200 OK" and within the response payload ("response content body" in HTTP parlance) have an application-specific error code that says "ID not found" or whatever.

Mike Nakis
  • 32,003
  • 7
  • 76
  • 111
  • Judging by the downvotes, I guess I must have hurt some people's feelings. Or maybe some other part of their body. C-:= – Mike Nakis Mar 26 '18 at 18:05
  • They should really read this: https://blogs.dropbox.com/developers/2015/04/how-many-http-status-codes-should-your-api-use/ – Mike Nakis Mar 26 '18 at 19:38
  • 1
    No hurt here. You're just wrong. Even the article you linked to doesn't mention using status codes so blatantly wrongly that errors and success look the same. It says, "Speaking of taste, it’s important to remember that API design isn’t strictly about the practical implications on client and server software. The audience for an API is the developer who is going to consume it. Per the “principle of least astonishment,” developers will have an easier time learning and understanding an API if it follows the same conventions as other APIs they’re familiar with." – cHao Mar 26 '18 at 22:29
  • @cHao so, I suppose the part that says "Dropbox currently uses about 10 different status codes (8 errors and 2 for success), but we’re planning to reduce that number in a future version of the API" did not mean anything to you. – Mike Nakis Mar 08 '19 at 18:19
  • Didn't mean what you're getting from it. If they know what they're doing, then at the most extreme, they'd reduce it to one success and four error codes (400, 401, 404, and 500), because they obviously care about conventions. – cHao Mar 08 '19 at 18:54
  • In fact, the next-to-last paragraph reads: "Following this pragmatic approach, APIs should probably use at least 3 status codes (e.g. 200, 400, 500) and should augment with status codes that have specific, actionable meaning across multiple APIs. Beyond that, keep your particular developer audience in mind and try to meet their expectations." – cHao Mar 08 '19 at 18:58