Is HTTP 404 an appropriate response for a PUT operation where some linked resource is not found?

25,541

There are a number of 4xx HTTP status codes. The most likely are either 404 or 409:

404 Not Found

The server has not found anything matching the effective 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.

409 Conflict

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 representation would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.

Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the representation being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response representation would likely contain a list of the differences between the two versions.

Either of those would be suitable, but I think I'd go for 409. 404 is used for URI not found but 409 indicates the current state of the resource doesn't allow the operation requested. In your case, the request can't be satisfied because something is amiss which doesn't allow it.

Share:
25,541
jwl
Author by

jwl

Updated on November 19, 2020

Comments

  • jwl
    jwl over 3 years

    Imagine a REST webservice where you are adding items to some type of container. For example, lets say we could add a attendee #789 to a event #456 like this:

    PUT http://..../api/v1/events/456/attendees/789
    

    If either event #456 or attendee #789 do not exist, is it correct to return an HTTP 404 (along with a detailed error payload explaining what the problem was, e.g. { "error" : { "message" : "Event 456 does not exist" , "code" : "404" } }?

    Similarly, what if I am creating something new which refers to another object, but the other object does not exist? For example, imagine I am creating an event at Location #123

    PUT http://..../api/v1/event
    { "location": 123, "name": "Party", "date": "2012-05-23", ...etc... }
    

    If Location #123 does not exist, is it also correct to return 404 (along with detail in response)? If not, what would be appropriate -- just a 400?

    According to the HTTP 1.1 spec http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

    9.6 PUT ... If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem

    So that would seem to be a good vote for responding with 404. However for some reason I can't quite put my finger on, responding to PUT (or POST) with a 404 seems odd to me... Perhaps it's because 404 means that the resource cannot be found, but in this case our resource is actually a linkage between two other resources, and it's one of those two resources that can't be found.

    Don't get too worried about my exact examples here -- they are made up to illustrate the point. The main question is: is 404 an appropriate response to a PUT operation that fails because a linked resource is not found?

    It would be excellent if you can point to references -- I'm having a hard time finding any that get into this level of detail and are also sufficiently credible. Especially as regards treatment of resource relationships in REST API design.

    Updated thinking I'm thinking that possibly the first example should return 404, the second should not. The reasoning being that in the first case the resource we're adding uses event 456 and attendee 789 as it's composite primary key; the second case location is only a foreign key. In the second case an error should be returned, but not a 404 -- possibly a 412 Precondition Failed or maybe just a 400 Bad Request. Thoughts?

  • jwl
    jwl almost 12 years
    409 is a possible choice. The part about "the user might be able to resolve the conflict and resubmit the request" is an interesting wrinkle. What if, to take my example, Locations cannot be added via the API, or possibly not by the user due to their security level -- is 409 still valid? Is it confusing if we return 404 for that type of error and 409 for other, nearly identical errors where the user can use the API to add the missing item? ... Still, 409 may not make sense since the users probably cannot create a Location with id# 123, assuming it's a automatically assigned key...
  • Andrew Leach
    Andrew Leach almost 12 years
    @joelarson: It doesn't say how the user should resolve the conflict. It may be by sending an email saying "Please add Location 123", and advice about how to do it might be included in the response. I would argue that if the situation is "You cannot do X because of situation Y" then it's 409; if it's "I can't locate URI 'X'" then it's 404.