HTTP response code for POST when resource already exists
Asked Answered
N

18

1335

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)?

Nankeen answered 29/9, 2010 at 21:26 Comment(6)
As of June 2016 FB blatantly sets 200 on registration when email existsGraupel
Github API returns 422 when trying to create a resource (team/repo) with a name that is already in useEncasement
It depends if you consider the existence of the object an error or not. If you process the append, 200 or 204 are the most appropriate response codes.Clite
In summary its a toss up between 409 Conflict and 422 Unprocessable Entity - I think the weight of answers here points to 409 though and certainly from a human perspective is more readily understandableAngola
@Graupel that will be to prevent account enumeration attacks.Uptake
I use 409 for this and 422 for bad forms only.Straightlaced
V
1631

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

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.

Vinni answered 29/9, 2010 at 21:31 Comment(17)
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).Benoite
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.Vinni
Note that the resource referenced by this part of the spec is the collection in which the client is trying to append a new object. If the server accepted the request to change the collection it would lead it to an inconsistent state caused by a previous change in the collection, which is the definition of version conflict. This helped me realize that this answer is probably correct. In this case the server could also include in the response a Link header referencing the existing resource or a hyperlink in the entity body.Paraffinic
@Vinni 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.Jobbery
@javajavajavajavajava: still, duplicate data is not a 'client error' in my mind, but that's in the eye of the beholder of course.Vinni
It's not. The intent of the 400 in both definitions is to tell the client to stop trying because the request is bad.Denizen
I return HTTP 409 with a Location header pointing to the existing/conflicting resource.Bitartrate
I still believe 409 is appropriate than 400. w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10Caban
@GrantGryczan the collection you're POSTing to is itself a target resource. In this case that would be POST /objects/.Nostalgia
This is also the code the Auth0 library uses for a case when a User already exists when you are trying to register.Glitter
Issuing a 409 instead of a generic 400 also lets a malicious user find emails that already exist in the system.Epiphyte
@GrantGryczan There's no implication that error 409 cannot be returned by a POST request. it can be used for version control, but is not required. From the spec: "Conflicts are most likely to occur in response to a PUT request" doesn't mean a POST is prohibited. Repeating your opinion in many of the other answers here doesn't make it any more correct. RFC7231 (published 4 years after the original question) makes it obvious that error 303 See Other is recommended for an existing resource, reporting where it is. For an append, as the OP stated, 200 or 204 would be more appropriate.Clite
@MavrickLaakso The ability to discover the existence of a resource in any system is not a problem if you have real security. What you're suggesting is "security through obscurity" which is generally recognized as not real security. Additionally, if a user is attempting to register an email address for a service, simply returning 400 is not useful, the user needs to know that email is taken so they can choose something else. Generically speaking, you can always authenticate a user prior to any attempts to create new resources.Monovalent
@Monovalent There isn't a right answer here, and there are tradeoffs to both. If I'm a malicious user, and the system respects status codes, a 409 lets me at least compile a list of valid emails to try to breach into. A 400 doesn't necessarily allow me to do the same. That was the point I was attempting to make.Epiphyte
422 just as an addition I agree with @GrantGryczan (https://mcmap.net/q/45371/-http-response-code-for-post-when-resource-already-exists) 422 Unprocessable Entity, which is used when a request is invalid but the issue is not in syntax or authenticationCaprification
@Epiphyte What if the system uses emails as the login identifier? If your system lets them know that an email is taken then they can just figure out this way.Lolanthe
Where did you quote your description from? link? -- Mozilla's description seems to fit nicely: "The HTTP 409 Conflict response status code indicates a request conflict with current state of the target resource. Conflicts are most likely to occur in response to a PUT request. For example, you may get a 409 response when uploading a file which is older than the one already on the server resulting in a version control conflict." - developer.mozilla.org/en-US/docs/Web/HTTP/Status/409 -- Keywords: "most likely.. to a PUT", meaning can be a POST, and "for example" not only.Sokil
F
178

It's all about context, and also who is responsible for handling duplicates of requests (server or client or both)


If server just point the duplicate, look at 4xx:

  • 400 Bad Request - when the server will not process a request because it's obvious client fault
  • 409 Conflict - if the server will not process a request, but the reason for that is not the client's fault
  • ...

For implicit handling of duplicates, look at 2XX:

  • 200 OK
  • 201 Created
  • ...

if the server is expected to return something, look at 3XX:

  • 302 Found
  • 303 See Other
  • ...

when the server is able to point the existing resource, it implies a redirection.


If the above is not enough, it's always a good practice to prepare some error message in the body of the response.

Felishafelita answered 8/8, 2018 at 11:58 Comment(3)
The request is not duplicating a resource, it is appending data to one. In my opinion, yours is the best answer of all.Clite
All 4xx errors are the client's "fault." All 5xx errors are the server's "fault." (And submitting duplicate data is something the client has to fix, not the server.)Wagonlit
@Paul Draper: There is no place for 5xx when the resource already exists. The order of 4xx, 2xx, 3xx is not a coincidence here. It will be mostly 4xx, but others are fair enough in many cases, especially when a client has totally no idea how to deal with a duplicate or it doesn't matter at all.Heartache
G
156

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.

Gaziantep answered 9/11, 2016 at 9:54 Comment(21)
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.Beholden
This is the most RESTful answer.Ryannryazan
just FYI.. IE does not return response body for a 303, if that matters.Ransell
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.Denizen
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.Neoprene
You don't have to be sorry. However, if the representation is equivalent to an existing resource, how can it have different properties? And even if it would have, how would a redirect be misleading? The OP says: I'm not sure what to do in case the object is already there. It is in fact the 'same' object. Why would a redirect be misleading? You're talking about another object which in the mind of the OP clearly isn't.Gaziantep
@Nullius: Quite right; I overlooked that final detail in the question. Apologies.Neoprene
@Nullius: SO is not letting me undo my downvote unless the question is edited. May I suggest you clarify that your answer is only appropriate for when the object is already there? I suspect I'm not the only person who overlooked that detail.Neoprene
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".Denizen
@Sinaesthetic: I think it's perfectly fine in some scenario's to let the client know 'hey, this one already exists, you can find it here'. The 'Ok I created it and it's over here' you mentioned, should be provided with the Content-Location header with the 201 Created or 200 Ok status codes. So, if something has been created, only 200 and 201 are valid return codes. This is also clearly stated in the same RFC I linked in my original answer. I agree that 303 might not be a correct answer in all situations or for all business cases. That is also the reason they stress the MAY in the RFC, I guess.Gaziantep
But what if the URL is the same but the method differs? For example you're not allowed to POST that here because you've posted it already, but you're allowed to PUT it here?Antitank
I also downvoted this. 4xx should be used instead. 3xx are supposed to be handled automatically from the client without user interaction. 4xx are client errors that users should take some action. In this case, change body payload, path variables, or do nothing.Toothlike
@Toothlike Could you provide a trustworthy source (e.g. IETF RFC) that a 3xx response coming from a REST service should be handled automatically by the client, without user interaction? I just referenced an RFC, exactly stating what I said in my original answer. If your point is valid, that RFC might need to be revised.Gaziantep
@Nullius, section 6.4 were states "The 3xx (Redirection) class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request". The user agent refers generally not to the client of the API, instead potentially the client that handles HTTP requests. From a API client users perspective, you may choose what fit best. In most cases, you aren't instered in the existing resource but in your POST response wen't OK.Toothlike
for instance, a redirection may be done as a side effect of your call from your HTTP client without you, client API even notice.Toothlike
Tbh, I still do not see a problem here. In section 6.4.4 about the 303 See Other status, right below the 3xx section you mentioned, it states "This status code is applicable to any HTTP method. It is primarily used to allow the output of a POST action to redirect the user agent to a selected resource, since doing so provides the information corresponding to the POST response". To me, it states even more clearly that a 303 is the right status as its result should correspond to a 'normal' POST response.Gaziantep
Thanks, IMHO this IS the correct answer for THIS question, Thanks for point to the RFC, it again states the same. you forgot to mention, the RFC points out that 303 should be accompanied with the "Location" response header,which can also be used for caching. this is beautiful. 409 conflict is NOT the right response for many reasons; 1. 4xx usually means they user did something bad and more. 409 may be perfect, for when trying to add a record where biz rule allows only for one record of this type...Chlorophyll
Agreed, to sum up: 300 codes are to help the client find the correct resource, 400 codes indicate the request won't be processed due to it's construction or content. So we can do either: - 303 redirect to the already created resource - 409 conflict if there is a reason to indicate error for recreation attemptsPrelatism
The consideration with using redirect codes is that many clients will automatically follow the redirect because that's the intent of a redirect. The caller of that http client would never even see the 3xx code, only the 200 result of the subsequent GET. So you you end up with this GET-like response for a POST operation and lose some context there. In some cases that's fine in other cases, the client might want to know that it was a duplicate. Can't tell you how many hours I've lost over the years troubleshooting that scenario.Denizen
Absolutely. Even a XHR request will get redirected, which might or might not suit your needs. The current answers/scenarios have a wider scope than the initial question imo, so it all boils down to the context: if you can expect duplicates in a normal workflow, a 303 might be exactly what you need to avoid unnecessary 'error' handling. If you don't expect duplicate calls, a 4xx with more elaborate error handling is the way to go, even if it isn't stated in the RFC.Gaziantep
But the result of processing the request would not be the same. The properties of an existing resource almost certainly differ from the new resource the client is attempting to create. Even if you ignore the fact that 3xx codes are for redirection and not for client errors, and the fact that the client doesn't care one bit about the resource you'd be redirecting to, this doesn't comply with the description of the status code that you cited.Makeup
L
119

Personally I go with the WebDAV extension 422 Unprocessable Entity.

According to RFC 4918

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.

Ledoux answered 29/9, 2010 at 21:44 Comment(8)
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.Nankeen
@Nankeen precisely; for instance, GitHub's API spits out 422 for malformed JSON bodies in POST requests.Spherule
Malformed JSON is not a syntactically correct entity, so a 422 strikes me as odd...Calvo
Ruby on Rails uses 422 for invalid data for years.Chickadee
GitHub's API returns a 422 status code when you try to create an already existing resource (e.g. a repository by the same name). The message it returns in the response is "Validation Failed"Etamine
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.Fineberg
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.Fulguration
@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.Constantino
S
51

After having read this and several other, years-long, discussions on status code usage, the main conclusion I came to is that the specifications have to be read carefully, focusing on the terms being used, their definition, relationship, and the surrounding context.

What often happens instead, as can be seen from different answers, is that parts of the specifications are ripped of their context and interpreted in isolation, based on feelings and assumptions.

This is going to be a pretty long answer, the short summary of which is that HTTP 409 is the most appropriate status code to report the failure of an "add new resource" operation, in case a resource with the same identifier already exists. What follows is the explanation why, based solely on what's stated in the authoritative source - RFC 7231.

So why is 409 Conflict the most appropriate status code in a situation described in the OP's question?

RFC 7231 describes 409 Conflict status code as follows:

The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource.

The key components here are the target resource and its state.

Target resource

The resource is defined by the RFC 7231 as follows:

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

So, when using a HTTP interface, we always operate on the resources identified by URIs, by applying HTTP methods to them.

When our intention is to add a new resource, based on the OP's examples, we can:

  • use PUT with the resource /objects/{id};
  • use POST with the resource /objects.

/objects/{id} is out of interest, because there can be no conflict when using a PUT method:

The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.

If the resource with the same identifier already exists, it will be replaced by PUT.

So we'll focus on the /objects resource and POST.

RFC 7231 says about the POST:

The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics. For example, POST is used for the following functions (among others): ... 3) Creating a new resource that has yet to be identified by the origin server; and 4) Appending data to a resource's existing representation(s).

Contrary to how the OP understands POST method:

Since POST is meant as "append" operation...

Appending data to a resource's existing representation is just one of the possible POST "functions". Moreover, what the OP actually does in the provided examples, is not directly appending data to the /objects representation, but creating a new independent resource /objects/{id}, which then becomes part of the /objects representation. But that's not important.

What's important is the notion of the resource representation, and it brings us to...

Resource state

RFC 7231 explains:

Considering that a resource could be anything, and that the uniform interface provided by HTTP is similar to a window through which one can observe and act upon such a thing only through the communication of messages to some independent actor on the other side, an abstraction is needed to represent ("take the place of") the current or desired state of that thing in our communications. That abstraction is called a representation [REST].

For the purposes of HTTP, a "representation" is information that is intended to reflect a past, current, or desired state of a given resource, in a format that can be readily communicated via the protocol, and that consists of a set of representation metadata and a potentially unbounded stream of representation data.

That's not all, the specification continues to describe representation parts - metadata and data, but we can summarize that a resource representation, that consists of metadata (headers) and data (payload), reflects the state of the resource.

Now we have both parts needed to understand the usage of the 409 Conflict status code.

409 Conflict

Let's reiterate:

The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource.

So how does it fit?

  1. We POST to /objects => our target resource is /objects.
  2. OP does not describe the /objects resource, but the example looks like a common scenario where /objects is a resource collection, containing all individual "object" resources. That is, the state of the /objects resource includes the knowledge about all existing /object/{id} resources.
  3. When the /objects resource processes a POST request it has to a) create a new /object/{id} resource from the data passed in the request payload; b) modify its own state by adding the data about the newly created resource.
  4. When a resource to be created has a duplicate identifier, that is a resource with the same /object/{id} URI already exists, the /objects resource will fail to process the POST request, because its state already includes the duplicate /object/{id} URI in it.

This is exactly the conflict with the current state of the target resource, mentioned in the 409 Conflict status code description.

Sialagogue answered 16/12, 2021 at 0:37 Comment(3)
Excellent explanation! You've convinced me against my own answer that argued against error 403.Makeup
But also, your answer should be updated since RFC 9110 now makes RFC 7231 obsolete.Makeup
Good point, Grant! Will go through it, to see what has been changed.Sialagogue
M
38

EDIT: I no longer fully agree with this and would now recommend error 409, but I'll leave my answer as-is since my original answer is what people upvoted. See bottom for what changed my mind. Upvote this only if you agree with my original answer:

I would go with 422 Unprocessable Entity, which is used when a request couldn't be processed but the issue is not in syntax or authentication. See RFC 9110:

The 422 (Unprocessable Content) status code indicates that the server understands the content type of the request content (hence a 415 (Unsupported Media Type) status code is inappropriate), and the syntax of the request content is correct, but it was unable to process the contained instructions. For example, this status code can be sent if an XML request content contains well-formed (i.e., syntactically correct), but semantically erroneous XML instructions.

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. There is no spec-compliant rationale for using a non-4xx error code to represent a client error.

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 action you are requesting is simply 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 (the resource you're trying to create) doesn't even exist yet. It's an error mainly for version control, when there is a conflict between the version of the resource stored and the version of the resource the client assumes in its request.

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

Edit: Error 422 is now standardized in HTTP by RFC 9110! It's no longer just part of WebDAV.

What changed my mind:

I changed my mind upon realizing my previous interpretation of error 409 was wrong while reading the new RFC 9110:

The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request. The server SHOULD generate content that includes enough information for a user to recognize the source of the conflict.

This does not restrict the intent of the error to version control as I originally thought it most likely did. It generalizes error 409 to conflicts of any kind. I do still think error 422 is applicable here, but because error 409 is more specific than error 422 (and furthermore, "Conflict" communicates the error's semantics more effectively to a human than "Unprocessable Entity" which is more generic), I would recommend that instead.

And for a great, comprehensive argument in favor of error 409, see this answer. The TLDR is that the "target resource" that has the conflict is actually the collection of resources you're posting to, not the resource you're creating, which is an interpretation more compliant with the spec (and that answer delves into exactly why). Upvote that answer if you agree with it, not this one!

(Note: My vote count was 31 at the time I changed my mind, so however many more/fewer votes this answer has now should help gauge how many people still agree/disagree with my old answer despite my edits.)

Makeup answered 7/4, 2018 at 16:32 Comment(15)
422 is webdav spec so I would not advise to use this for a REST APIPliske
@Pliske Why not? It is fairly conventional, clearly fits the purpose, and communicates what it is intended to.Makeup
@GrantGryczan because it's meant for something else. Some clients will behave accordingly, implementing the webdav spec "correctly". I've inadvertently locked up production web clients due to this fact and it was pretty hard to figure out what the heck was going on. Don't use webdav codes for anything other than webdav.Denizen
@Denizen If I'm understanding correctly, WebDAV itself is a protocol intending to extend HTTP. By using status code 422, you are using WebDAV. So I don't know what you mean by this. Am I misunderstanding what WebDAV is? And if what you say is right, then why does GitHub use it for this purpose?Makeup
@GrantGryczan it's right in your statement - it's an extension. What I mean by this is that those codes have meaning that some clients will action on so if it's not implemented correctly by both sides, client and server, you may have some serious issues. For example, some codes cause semi-stateful behavior like 1xx series codes, where clients will not hangup and return control to the application until they get followup messages. In .NET, if you return 102, that connection will remain open until a final message is returned and the framework doesn't even have a hook for that.Denizen
Just to add more context to the above, 102 is how the server says "I'm not hungup, im still processing, please don't timeout". The client implementation compliments by bypassing or extending its normal timeout setting. I ran into this problem when we were having client hang forever because the server never completed the call and the client never closed the connection. The reason being is because we used the WebDav codes to communicate a message but did not fully implement it as it was designed but the client lib did. That's why they're annotated as WebDav and not just part of HTTP properDenizen
@Denizen That just sounds like an issue due to you misusing it, not an issue inherent to using it at all?Makeup
@GrantGryczan that's kind of my point. The chances of someone using a WebDav code "correctly" is pretty slim since virtually no one will do the necessary research on special codes. To most developers, http codes are just numbers that communicate the nature of a result, not necessarily part of a specification that would imply any assumed mechanics. I'm just calling this out as a warning. If you're not going to put in the time to implement the WebDav codes fully, it's probably better to avoid them completely lest you hit a serious and baffling problem in prod at some random future date.Denizen
@Denizen But all you have to do to use it in this case is set status code 422. I don't see how misuse is likely here, especially to the extent that you would advise against using status code 422 in general.Makeup
@Denizen Heh, look at that! Error 422 is now official (IETF) standard as of RFC 9110.Makeup
@Pliske as well, ^Makeup
@GrantGryczan if it's no longer a WebDav code, then +1 from me. The way it is written though... I wonder if this would now become a more appropriate code for validation failures too or only certain kinds of validation failures?Denizen
@Denizen Well, most validation failures fall under error 400, since they are problems in the syntax of the request, and/or they prevent the server from understanding the request. Error 422 implies the server did understand the request but was unable to obey its instructions regardless. Also, although 422 is now an HTTP code, you might notice I changed my answer anyway, and I no longer would use 422 for this.Makeup
@GrantGryczan let me rephrase -- it implies that 400 still stands for validation failures due to improper syntax, but it kind of implies that 422 implies it would be well suited for validation failures on the business logic side (semantic, invariant, etc.) where the failure is not related to the state of the system.Denizen
@Denizen I see, that's understandable.Makeup
S
33

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.

10.4.4 403 Forbidden

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.

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

Stalinsk answered 24/12, 2015 at 22:40 Comment(5)
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.Elmiraelmo
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.Stalinsk
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.Makeup
I would not infer that a 409 error cannot be returned by a POST, in fact, I would infer the opposite because "Conflicts are most likely to occur in response to a PUT request." seems to indicate that other request methods can also use this code. Additionally, "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." (webdav.org/specs/rfc2616.html#status.409)Monovalent
(I no longer agree with my above comment. An explanation of what changed my mind can be seen at the bottom of my answer.)Makeup
R
20

In your case you can use 409 Conflict

And if you want to check another HTTPs status codes from below list

1×× Informational

100 Continue
101 Switching Protocols
102 Processing

2×× Success

200 OK
201 Created
202 Accepted
203 Non-authoritative Information
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status
208 Already Reported
226 IM Used

3×× Redirection

300 Multiple Choices
301 Moved Permanently
302 Found
303 See Other
304 Not Modified
305 Use Proxy
307 Temporary Redirect
308 Permanent Redirect

4×× Client Error

400 Bad Request
401 Unauthorized
402 Payment Required
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Timeout
409 Conflict
410 Gone
411 Length Required
412 Precondition Failed
413 Payload Too Large
414 Request-URI Too Long
415 Unsupported Media Type
416 Requested Range Not Satisfiable
417 Expectation Failed
418 I’m a teapot
421 Misdirected Request
422 Unprocessable Entity
423 Locked
424 Failed Dependency
426 Upgrade Required
428 Precondition Required
429 Too Many Requests
431 Request Header Fields Too Large
444 Connection Closed Without Response
451 Unavailable For Legal Reasons
499 Client Closed Request

5×× Server Error

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates
507 Insufficient Storage
508 Loop Detected
510 Not Extended
511 Network Authentication Required
599 Network Connect Timeout Error
Rist answered 4/6, 2020 at 23:57 Comment(0)
F
12

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.

Fabricant answered 30/9, 2014 at 10:12 Comment(8)
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?Leisure
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.Fabricant
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.Ferris
@Leisure Stop using PKs as public IDs!!Denizen
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 impossibleBundy
When an entity has an unique constraint, the server must response 409 CONFLICT. I think it's not the point of the question. When you PUT an item and the item already exists (id) you can modify it, but there will be an 409 if you duplicate an Unique constraint.Fabricant
Old thread, sorry, but PUT is ubiquitously accompanied by an ID because it is a replace or create. If you provide the ID to a new resource then the resource server should use that ID. This messes with peoples' heads because "you can't tell the database what ID to use!" But that's a different problem because you shouldn't be using PKs as an ID to begin with hence the confusion. PKs are a DB implementation detail that you're leaking. Use an application ID that's assigned by your domain on creation and it begins to make more sense.Denizen
For relationships - Add a new manager POST /managers add or replace PUT /managers/{id} Add an employee to a manager POST /managers/{id}/direct-reports Add or replace employee PUT /managers/{id}/direct-reports/{id} etc. The rest (e.g. constraints) is validation. 1:1 relationships and partial updates can be handled the same way or as singular properties that are PATCH'ed. Also if you need multiple steps then use multiple steps, ex. POST /users followed by POST /managers/{id}/direct-reports/{user-id-returned-by-previous-call}Denizen
C
8

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

Comminute answered 16/5, 2012 at 9:25 Comment(8)
3xx statuses are meant for redirectionGarnett
"The requested resource resides temporarily under a different URI." from w3.org/Protocols/rfc2616/rfc2616-sec10.htmlColpitis
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".Comminute
@DavidVartanian Hum... I dont see an error here. The client send a right request, but how to say "Sorry, but what you are trying to create here already exists THERE"? Seems a job for some 3xx. It is not a 4xx for me, as there is no client error.Comminute
that's an error!! what's an error for you? The client tried to execute an operation, but it could not finish it due to a specific reason: the entity you are trying to create already exists!Riyal
Who made the mistake? The server or the client?Comminute
I really think that neither. The client had no mistake, so no 4xx here. The server had no mistake, so no 5xx here.Comminute
@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.Comminute
D
7

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

Denizen answered 27/10, 2016 at 4:51 Comment(3)
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.Makeup
Debatable imo. If you post to /users then the resource is the collection instead of the individual record /users/{id}Denizen
(I no longer agree with my above comment. An explanation of what changed my mind can be seen at the bottom of my answer.)Makeup
G
3

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

Gleeson answered 7/9, 2015 at 11:33 Comment(2)
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.Denizen
They don't want to update an existing item. They want to create a new item, and there's a name conflict.Makeup
W
2

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.

Would answered 31/7, 2015 at 18:7 Comment(6)
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.Gleeson
As I said, I don't thing this is a error. But I see the point of @martinWould
If the resource is not successfully created, then there is by definition an error.Makeup
POST is also used for appending data. This is by definition, not an error.Clite
@Clite Even given that's the case, if the data is not successfully appended, there is still an error. And if the resource already exists, no data is going to be appended.Makeup
"The members of a DAV binding have already been enumerated in a previous reply to this request, and are not being included again."Would
M
2

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://www.rfc-editor.org/rfc/rfc7231#section-6.4.1

Mccauley answered 2/1, 2017 at 14:1 Comment(2)
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.Discussant
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"..Denizen
A
2

More likely it is 400 Bad Request

[**6.5.1. 400 Bad Request**][1]


The 400 (Bad Request) status code indicates that 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).

As the request contains duplicate value(value that already exists), it can be perceived as a client error. Need to change the request before the next try.
By considering these facts we can conclude as HTTP STATUS 400 Bad Request.

Anh answered 6/8, 2018 at 9:3 Comment(1)
Bad Request means that there is an inherent problem with the syntax of the packet. If, in another context (such as the resource not already existing), the packet would succeed, then it should not return error 400.Makeup
J
2

Since you mentioned that the object create request using post contains the ID of the object, you should make it an idempotent request. Just return the exact same response as a successful create request. Idempotent request makes APIs simpler, eg. now client doesn't have to worry about 2 different cases (success, failure). or client can safely retry the request, in case something goes wrong in connectivity/ server temporarily down.

Japha answered 18/7, 2022 at 14:24 Comment(1)
This makes sense sometimes. But other times you want to error. For example if a user tries to create an account with an email that already exists. They should see an error and be instructed to login insteadKneedeep
S
0

Error 402, payment required

I.E. this resource already exists but if you give me enough money I'll delete the current one and give it to you :D

...but looking at mozilla's definition of status codes at https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses

as a more serious answer that no one has provided here, what about 451: unavailable for legal reasons. You cannot "legally(by terms and conditions put in place by yourself)" give multiple people access to the same account information

422 is also a good option which is Unprocessable Entity The request was well-formed but was unable to be followed due to semantic errors. since it is a perfectly valid request but due to it being semantically equal to another entry, it cannot be followed.

Selfheal answered 2/8, 2021 at 13:12 Comment(3)
Hahaha, I love this!Spaak
Is 451 not for GET requests? As the spec says ...indicates that the user requested a resource that is not available due to legal reasons, such as a web page for which a legal action has been issuedSoane
This is funny but, unless you're just making a REST API as a joke and not for a public production application, please don't actually use error 402 or 451 for this. Either would be extremely confusing. This has nothing to do with payment or legal terms.Makeup
S
-10

This is a user side fault and belongs to 4xx group. This is the right answer https://developers.rebrandly.com/docs/403-already-exists-errors

Stowell answered 23/6, 2020 at 15:49 Comment(4)
403 is forbiddenAgog
you are right @selalerer, the client is forbidden to perform the operation (adding the same resource)Stowell
This is not an authoritative source of error code definitions, it is their list of their definitions for codes for their API.Baun
Why Rebrandly chose to alter the HTTP response code spec instead of just adding new codes at the end is strange. @ManjunathBhadrannavar may have already learned in the past two years, but 401 Unauthorized means the user isn't authenticated (Missing or bad credentials) and 403 Forbidden means not authorized (Good credentials, but lacks permission for that endpoint). 403 is not the right choice here because it has nothing to do with the client lacking permissions.Inspiration

© 2022 - 2024 — McMap. All rights reserved.