HTTP response code for POST when resource already exists


HTTP response code for POST when resource already exists



I'm building a server that allows clients to store objects. Those objects are fully constructed at client side, complete with object IDs that are permanent for the whole lifetime of the object.



I have defined the API so that clients can create or modify objects using PUT:


PUT /objects/{id} HTTP/1.1
...

{json representation of the object}



The {id} is the object ID, so it is part of the Request-URI.



Now, I'm also considering allowing clients to create the object using POST:


POST /objects/ HTTP/1.1
...

{json representation of the object, including ID}



Since POST is meant as "append" operation, I'm not sure what to do in case the object is already there. Should I treat the request as modification request or should I return some error code (which)?





As of June 2016 FB blatantly sets 200 on registration when email exists
– Green
Jun 21 '16 at 11:50





Github API returns 422 when trying to create a resource (team/repo) with a name that is already in use
– Ken
Dec 15 '16 at 16:44




13 Answers
13



My feeling is 409 Conflict is the most appropriate, however, seldom seen in the wild of course:


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 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.



Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity 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 entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.





why not go for 400 Bad Request? For me this looks a bit like a validation error (you are providing wrong payload with illegal id).
– manuel aldana
Sep 30 '10 at 18:55





400 => "The request could not be understood by the server due to malformed syntax". And the server understands perfectly, but is unable to comply due to a conflict. There is nothing wrong with the request & syntax, only a data problem. A 400 would instantly make me believe the whole mechanism I'm using is flawed, instead of just the data.
– Wrikken
Sep 30 '10 at 19:11





@Wrikken That is no longer correct. HTTP 400 was changed in RFC 7231 to mean "the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing)." I'm not saying 400 is correct usage in this case but it could be correct with the new definition of 400.
– javajavajavajavajava
Jun 21 '16 at 18:16






@javajavajavajavajava: still, duplicate data is not a 'client error' in my mind, but that's in the eye of the beholder of course.
– Wrikken
Jul 16 '16 at 23:45





I return HTTP 409 with a Location header pointing to the existing/conflicting resource.
– Gili
Oct 10 '17 at 18:51


HTTP 409


Location



Personally I go with the WebDAV extension 422 Unprocessable Entity.


422 Unprocessable Entity



REST Patterns describes it as



The 422 Unprocessable Entity status code means the server understands the content type of the request entity (hence a 415 Unsupported Media Type status code is inappropriate), and the syntax of the request entity is correct (thus a 400 Bad Request status code is inappropriate) but was unable to process the contained instructions.


422 Unprocessable Entity


415 Unsupported Media Type


400 Bad Request





This is an interesting thought, and prompted me to finally read the WebDAV RFC. However, I think the meaning of 422 is that the request and the included entity were syntactically correct but semantically didn't make sense.
– vmj
Sep 30 '10 at 6:24





Malformed JSON is not a syntactically correct entity, so a 422 strikes me as odd...
– awendt
Jul 22 '14 at 9:41


422





I would not go with this. From the same URL referenced in the answer: "For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions." This is the real meaning of an unprocessable entity, unlike the case when you send completely valid request entity with valid syntax AND semantics, but the only problem is that it conflicts with an existing entity. Actually, if the semantics of the request entity were not valid, there should not be a similar, existing entity at all.
– Tamer Shlash
Dec 4 '15 at 6:51






Adding to Tamer comment, if the second request came first, then it would succeed, which will not possible if that was semantically correct. Hence in correct semantics wouldn't apply here.
– Harish
Apr 14 '16 at 6:46





@Tamer Why so? The command "Please create object xy" is syntactically correct. It is semantically correct only if it is possible to create object xy. If object xy already exists, it can no longer be created, hence this is a semantic error.
– Hagen von Eitzen
Jul 20 '17 at 20:55



According to RFC 7231, a 303 See Other MAY be used If the result of processing a POST would be equivalent to a
representation of an existing resource
.





In my opinion, this might a well be the accepted answer. Though "MAY" indicates a completely optional item, it is the only response code suggested by the official RFC 7231 documentation.
– Nando
Nov 19 '16 at 15:18





This is the most RESTful answer.
– Seth
Nov 28 '16 at 21:29





just FYI.. IE does not return response body for a 303, if that matters.
– dave4jr
Feb 21 '17 at 12:44






I think context is important. For example: returning a 303 implies a redirection to the found resource is needed. That might make sense in a server to server call, but if you were running through a user registration process, it would make no sense at all.
– Sinaesthetic
Jun 3 '17 at 19:00





Sorry, I'm downvoting this. The HTTP 300s are about redirecting, and redirecting to another object which probably has different properties would be very misleading.
– Michael Scheper
Jun 21 '17 at 22:41



Late to the game maybe but I stumbled upon this semantics issue while trying to make a REST API.



To expand a little on Wrikken's answer, I think you could use either 409 Conflict or 403 Forbidden depending on the situation - in short, use a 403 error when the user can do absolutely nothing to resolve the conflict and complete the request (e.g. they can't send a DELETE request to explicitly remove the resource), or use 409 if something could possibly be done.


409 Conflict


403 Forbidden


DELETE



The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated. If
the request method was not HEAD and the server wishes to make public
why the request has not been fulfilled, it SHOULD describe the reason
for the refusal in the entity. If the server does not wish to make
this information available to the client, the status code 404 (Not
Found) can be used instead.



Nowadays, someone says "403" and a permissions or authentication issue comes to mind, but the spec says that it's basically the server telling the client that it's not going to do it, don't ask it again, and here's why the client shouldn't.



As for PUT vs. POST... POST should be used to create a new instance of a resource when the user has no means to or shouldn't create an identifier for the resource. PUT is used when the resource's identity is known.


PUT


POST


POST


PUT



...



The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations. In
contrast, the URI in a PUT request identifies the entity enclosed with
the request -- the user agent knows what URI is intended and the
server MUST NOT attempt to apply the request to some other resource.
If the server desires that the request be applied to a different URI,



it MUST send a 301 (Moved Permanently) response; the user agent MAY
then make its own decision regarding whether or not to redirect the
request.





I think 403 Forbidden implies that, even though the user is authenticated, he is not authorized to execute the requested action. I would not use it for validation errors. Example: Not logged in, I attempt to delete something. Server sends me 401 Unauthorized (which is just badly named, should be 401 Unauthenticated). I log in and try again. This time the server checks my permissions, sees i'm not allowed and returns 403 Forbidden. Also see this question.
– Stijn de Witt
Feb 20 '17 at 13:41





Hm... true. The thought here was jumping right to telling the user that their authorizations make the resource immutable in the OP's use-case - it already exists, you have no permission to do anything to resolve the conflict, don't try creating the resource again.
– p0lar_bear
Jun 22 '17 at 14:35





According to the spec, it is implied that error 409 cannot be returned by a POST request (when used correctly), as it states that it should be returned when it conflicts with the target resource. Since the target resource has not yet been posted to, it cannot possibly conflict, and thus to reply with 409 Conflict does not make any sense.
– Grant Gryczan
Jun 28 at 16:44


POST


409 Conflict



What about returning a 418?



Because the client ask to persist an entity that already exists on the server, the server finally gets mad and think he's a teapot and return: 418 I'm a teapot.


418 I'm a teapot



References:





Do not return a 418 code. Ever. Although this answer is obviously meant to be a joke, it could be misleading for beginners or people less comfortable with HTTP.
– jbmusso
Mar 30 at 15:54



"302 Found" sounds logical for me. And the RFC 2616 says that it CAN be answered for other requests than GET and HEAD (and this surely includes POST)



But it still keeps the visitor going to this URL to get this "Found" resource, by the RFC. To make it to go directly to the real "Found" URL one should be using "303 See Other", which makes sense, but forces another call to GET its following URL. On the good side, this GET is cacheable.



I think that I would use "303 See Other". I dont know if I can respond with the "thing" found in the body, but I would like to do so to save one roundtrip to the server.



UPDATE: After re-reading the RFC, I still think that an inexistent "4XX+303 Found" code should be the correct. However, the "409 Conflict" is the best existing answer code (as pointed by @ Wrikken), maybe including a Location header pointing to the existing resource.





3xx statuses are meant for redirection
– Aviram Net
Aug 20 '14 at 12:44






"The requested resource resides temporarily under a different URI." from w3.org/Protocols/rfc2616/rfc2616-sec10.html
– statueofmike
Aug 20 '14 at 20:06





IMHO, "307 Temporary Redirect" is the real temporary redirect. "302" is ambiguous, but "FOUND!!" is the really desired message here. The best unambiguous compromise is "303 See Other" on the HTTP semantics. I would go with "303 See Other".
– alanjds
Aug 22 '14 at 16:21






3xx codes are not errors!
– David Vartanian
Apr 27 '15 at 7:46





@DavidVartanian Thanks for the discussion. Updated the answer towards 409. The client is wrong to ask for impossible stuff, even if it does not know that it is impossible.
– alanjds
May 20 '16 at 19:17




I don't think you should do this.



The POST is, as you know, to modify the collection and it's used to CREATE a new item. So, if you send the id (I think it's not a good idea), you should modify the collection, i.e., modify the item, but it's confusing.



Use it to add an item, without id. It's the best practice.



If you want to capture an UNIQUE constraint (not the id) you can response 409, as you can do in PUT requests. But not the ID.





What about an object that has a join table relation? Say we have account, product, and account_product as database tables. I want to add a product to an account, so I would want to post to /account/{id}/product with the product_id. If only one account-product relationship is allowed, what should I return?
– partkyle
Oct 2 '14 at 0:11






Forget the database tables. Let's say a product can only be related to an account... Then it's one to many relationship. So, POST /product/{id} with {'account':account_id}. If you have the max cardinality set to '1' (one to one relationship).... Why are they separated rest objects? An error of cardinality will be just a 400 err. Keep it simple. I hope I understood your question.
– Alfonso Tienda
Oct 10 '14 at 13:00





I just posed this question also and for me the ID is not the technical ID on the database but the something like the company code. In this application a manager user can create companies and has to give them a code. This is the company ID for the user, despite the fact that the DB table also has a technical ID. So in my case I'll return a 409 if the same company code already exist.
– AlexCode
Nov 26 '14 at 8:24





@partkyle Stop using PKs as public IDs!!
– Sinaesthetic
Oct 27 '16 at 4:46






Some entities have unique constraints on them, not just the id. Like an account, you can't create an account if user doesn't provide username. And adding an account with no username is obviously impossible
– rocketspacer
Nov 3 '16 at 15:38




I think for REST, you just have to make a decision on the behavior for that particular system in which case, I think the "right" answer would be one of a couple answers given here. If you want the request to stop and behave as if the client made a mistake that it needs to fix before continuing, then use 409. If the conflict really isn't that important and want to keep the request going, then respond by redirecting the client to the entity that was found. I think proper REST APIs should be redirecting (or at least providing the location header) to the GET endpoint for that resource following a POST anyway, so this behavior would give a consistent experience.



EDIT:
It's also worth noting that you should consider a PUT since you're providing the ID. Then the behavior is simple: "I don't care what's there right now, put this thing there." Meaning, if nothing is there, it'll be created; if something is there it'll be replaced. I think a POST is more appropriate when the server manages that ID. Separating the two concepts basically tells you how to deal with it (i.e. PUT is idempotent so it should always work so long as the payload validates, POST always creates, so if there is a collision of IDs, then a 409 would describe that conflict).





According to the spec, it is implied that error 409 cannot be returned by a POST request (when used correctly), as it states that it should be returned when it conflicts with the target resource. Since the target resource has not yet been posted to, it cannot possibly conflict, and thus to reply with 409 Conflict does not make any sense.
– Grant Gryczan
Jun 28 at 16:41


POST


409 Conflict





Debatable imo. If you post to /users then the resource is the collection instead of the individual record /users/{id}
– Sinaesthetic
Jun 29 at 23:21





It's an error specifically for version control, when there is a conflict between the version of the resource stored and the version of the resource requested. It's very useful for that purpose, for example when the client has cached an old version of the resource and sends a request based on that incorrect version which would no longer be conditionally valid. "In this case, the response representation would likely contain information useful for merging the differences based on the revision history."
– Grant Gryczan
Jun 30 at 7:16






I do like your suggestion to use PUT though.
– Grant Gryczan
Jun 30 at 7:27


PUT



Another potential treatment is using PATCH after all. A PATCH is defined as something that changes the internal state and is not restricted to appending.



PATCH would solve the problem by allowing you to update already existing items. See: RFC 5789: PATCH





Patch is like PUT but not a complete replacement. It's used to modify a piece of the resource like adding, removing, or modifying a single element of the resource instead of replacing it as a whole.
– Sinaesthetic
Oct 27 '16 at 4:45



Why not a 202 Accepted? It's an OK request (200s), there were no client errors (400s), per se.



From 10 Status Code Definitions:



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



... because it didn't need to be completed, because it already existed. The client doesn't know it already existed, they didn't do anything wrong.



I'm leaning on throwing a 202, and returning similar content to what a GET /{resource}/{id} would have returned.


/{resource}/{id}





This answer is wrong. 202 means that the server did not find a problem with the request, but chose to process the request after responding. It also means that it expects that the processing to be successful. In our case the server knows that the processing will fail, so 202 is the wrong response.
– Adrian
Jul 26 '16 at 0:12





An example of 202 would be a queue or subscription. In other words, the result of the request may not be available immediately if you were to query it right this moment.
– Sinaesthetic
Oct 27 '16 at 4:41





It's a success code because it means that it will be completed. It just hasn't yet. There actually is a client error, being that the resource being posted already exists. You would use a 4xx code.
– Grant Gryczan
Jun 28 at 16:39



4xx



What about 208 - http://httpstatusdogs.com/208-already-reported ? Is that a option?



In my opinion, if the only thing is a repeat resource no error should be raised. After all, there is no error neither on the client or server sides.





This is no option due you want to append a certain item which id is already existing. So you try to add something but this is already there. A OK would be only apply if the data set was grown. Append Something -> Ok I appended nothing. Does not fit, I guess.
– Martin Kersten
Sep 7 '15 at 11:27





A 2xx error code cannot indicate an error.
– Grant Gryczan
Jun 28 at 16:36


2xx



Stumbled upon this question while checking for correct code for duplicate record.



Pardon my ignorance but I don't understand why everyone is ignoring the code "300" which clearly says "multiple choice" or "Ambiguous"



In my opinion this would be the perfect code for building a non standard or a particular system for your own use. I could be wrong as well!



https://tools.ietf.org/html/rfc7231#section-6.4.1





My understanding: "status code indicates that the target resource has more than one representation ... information about the alternatives is being provided so that the user (or user agent) can select a preferred representation by redirecting its request to one or more of those identifiers" We are explicitly trying to prevent more than one representation. There are no options. There are no alternatives for the client to choose from. The client should resubmit with a different id. With that said, one should also consider whether unique ids should be generated in the client vs. server.
– musicin3d
Feb 14 '17 at 2:17





Semantically, the client is saying "Create this" and the server is responding by saying "Go here instead". The conversation doesn't make any sense. It's almost as if the server is telling the client to "post to this location instead". 300s are more a more appropriate response to a GET request or a POST in the case where the server is responding with "Ok I created it and it's over here"..
– Sinaesthetic
Apr 4 at 19:15






A 3xx error code cannot indicate an error.
– Grant Gryczan
Jun 28 at 16:36


3xx



I would go with 422 Unprocessable Entity, which is used when a request is invalid but the issue is not in syntax or authentication.


422 Unprocessable Entity



As an argument against other answers, to use any non-4xx error code would imply it's not a client error, and it obviously is. To use a non-4xx error code to represent a client error just makes no sense at all.


4xx


4xx



It seems that 409 Conflict is the most common answer here, but, according to the spec, that implies that the resource already exists and the new data you are applying to it is incompatible with its current state. If you are sending a POST request, with, for example, a username that is already taken, it's not actually conflicting with the target resource, as the target resource has not yet been posted to. It's an error specifically for version control, when there is a conflict between the version of the resource stored and the version of the resource requested. It's very useful for that purpose, for example when the client has cached an old version of the resource and sends a request based on that incorrect version which would no longer be conditionally valid. "In this case, the response representation would likely contain information useful for merging the differences based on the revision history." The request to create another user with that username is just unprocessable, having nothing to do with version control.


409 Conflict


POST



For the record, 422 is also the status code GitHub uses when you try to create a repository by a name already in use.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

.

Delphi Android file open failure with API 26

How to generate build files in next js