-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Possible IntegrityError even with UniqueValidator #3876
Comments
I do agree with the 500 not being what we would expect, but isn't a 400 with the correct validation error more appropriate? |
I prefer 409 here, though certainly a 400 is still "correct":
I am not sure what the concern about other backends would be? if they didn't raise an error even in the case of a conflict, then there is nothing to catch. |
I was just fishing about the backends it may be a totally different reason. To me a race condition raising a unique constraint exception or a Again I'm not sure what are the constraints are here as the |
Ah ok. If 400s are raised now then sure. For some reason I thought 409s were being raised, but you are right. (and now I recall this discussion]).
See: https://groups.google.com/forum/#!topic/django-rest-framework/d8LV38uFW_I/discussion |
Ha sweet! That's what I was looking for so yes, this seems to be a tricky use case... |
I'm reluctant to bring in complexity in favor of a theoretical - yet possible - use case. |
In addition to handling the possible race, having the framework handle the errors coming back from the DB also make it easier for the user to remove the validators in the serializers / fields to improve performance but removing the extra query. Right now the user then needs to handle the exceptions being raised by the DB rather than having the framework deal with it. |
I'd be interested to see this replicated locally if possible, as that'd make it easier to more thoroughly verify a fix - any idea how easy/difficult it is to trigger, and if we have any/many sites that'd come across this in production? |
@tomchristie that should be fairly easy to reproduce.
First should be saved, second would raise a DB error. |
I was more meaning replicate the issue given an actual view & incoming requests. Mocking out a non-real-world example may be handy tho'. |
It is nearly impossible to reproduce this kind of issue without relying on some luck. |
Any similar issue raised against ModelForm in Django's tickets, perhaps? |
I guess setting up a view with a edit: the sleep should occur after the serializer validation. |
That'd be interesting to see for a start, yes. Tho still useful to know at what point you need to get to in load until this starts to become viable. And Eg. what status have the Django Core team attached to the same issue with ModelForm? Closed as wontfix, or something else? |
Going to close this along same lines as https://code.djangoproject.com/ticket/9581 If anyone is actually hitting this in production it'd be useful to know, but either way around I don't see it as likely that we'll do anything other than allowing the 5xx response by default - if you need something else, write some view code, and catch the exceptional case. |
Seems acceptable to me. |
I'm only reviving this since you wrote that it'd be useful to know if someone was hitting this in production. |
Okay. If you get any further digging into that do shout out here. Useful for broader context. |
I've got this exact issue occurring on my company's production system, and can more or less reliably replicate by sending rapid, identical PATCH requests to one of our endpoints. A UniqueTogetherConstraint on a model is violated despite the UniqueTogetherValidator being in place. I'm about to patch our serializer to just catch and handle the raised Integrity errors, transforming them to drf Validation errors instead. Not the end of the world, but it does seem counterintuitive that UniqueTogetherValidator has a race condition which isn't mentioned in the docs. And to be consistent I need to parse the IntegrityError message and transform it to look just like the normal UniqueTogetherValidator message, which is non-trivial. Naively, I expected UniqueTogetherValidator to handle this. |
Hi @fildred13. Ideally, #6172 will be merged in 3.11, which should fix the race condition. |
@fildred13 Also worth confirming if you're using |
We encountered this problem in production as well and we're not doing anything fancy in the save method that would increase the window between validation and saving to the database. I was able to create a minimal verifiable example that you can clone here. The gist of it: from django.db import models
class Entry(models.Model):
slug = models.SlugField(unique=True)
This also happens with Would you consider this a case that should be handled by DRF? |
Even if a Serializer field is using
UniqueValidator
(likewise forUniqueTogetherValidator
) there is still a race where after the check is performed, a conflicting row may be added to the DB. Right now that results in a 500 error with something like the following:I suggest in these cases DFF return a
409
with a generic error message. At the very least there should be some opt in behavior to get this.I do think this logic should be handled by the framework rather than by the application.
The text was updated successfully, but these errors were encountered: