-
Notifications
You must be signed in to change notification settings - Fork 504
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
'User' object has no attribute 'is_verified' #3459
Comments
Assigning to @getsentry/support for routing ⏲️ |
@omerfarukabaci, I am having trouble reproducing your issue from the information you have provided. Could you please provide your source code (if it is public), or create a minimal reproduction that you can share with me? |
Hey @szokeasaurusrex, thank you for your quick answer! Unfortunately our source code is not public. I have tried to create a minimal reproduction but couldn't manage to do that, since the issue is flaky and does not happen all the time. But I have some events on Sentry, would that work? In the traces of those events, it can be seen that |
Hey @omerfarukabaci, any additional info would help, even just the full stack trace. Sentry events too -- feel free to put the links to them here or if you prefer, send them to me on Discord ( |
Hey @sentrivana, I have sent Sentry event links to your email. There is one other issue that started appearing after enabling profiling, I am not 100% sure that it is directly related with profiling but seems like it, also added link to that to the email just in case. If you need further assistance on my side please let me know, I can override the Thanks a lot for your prompt responses! 🚀 |
Sure thing, that's why we're here :) Thanks for the quick follow ups!
So I've taken a look at the Sentry events and while the stacktraces provide some extra context, I'm still not sure what's going on, especially why profiling specifically would be causing this. The facts we have so far:
Some follow-ups:
I had a quick look but don't have many insights -- if you keep seeing this and it indeed looks like a profiler/SDK issue, can you please open a new issue just with that? Makes it easier for us to keep track. :) |
@sentrivana Thanks for the detailed response! Some comments about the facts:
Now I have realized that this is not the case, sorry for the initial misinformation. To test this I have opened up our QA and Sandbox admin pages and refreshed them tens of times, and eventually I could see the same error again, so it doesn't only happen on the first request but happens occassionally.
I have checked the deployments just before encountering this issue for the first time, and the issue is introduced after a deployment that includes:
Then the issue disappeared after I have removed
Then one week after not seeing the issue, I have enabled profiling again, then immediately we have started seeing this issue again, which is why I strongly suspect that this is related with profiling.
Is this sampling being executed in another thread? If you look at the traces of the issues hapenning in the same page with ids:
You can see that the error is happening at different times. Also the span that raises the error seems like: Follow-ups
Yes, copy & pasting from the settings source code: INSTALLED_APPS = [
...,
"django_otp",
"django_otp.plugins.otp_static",
"django_otp.plugins.otp_totp",
]
MIDDLEWARE = [
m
for m in [
...
("django_otp.middleware.OTPMiddleware" if ROLE == "admin" else None),
]
if m
] I thought that maybe we somehow cannot set or change the
Copy & pasting the whole sentry config from the settings source code: import os
import re
SENTRY_DSN = os.environ.get("SENTRY_DSN")
SENTRY_ENV = os.environ.get("SENTRY_ENV")
if SENTRY_DSN:
if not SENTRY_ENV:
raise RuntimeError(
"SENTRY_ENV env var needs to be defined (use role name, such as 'admin' or 'buyer_console')"
)
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
def traces_sampler(sampling_context):
path = sampling_context.get("wsgi_environ", {}).get("PATH_INFO")
method = sampling_context.get("wsgi_environ", {}).get("REQUEST_METHOD")
if path == "/favicon.ico":
return 0
if path.startswith("/static/"):
return 0
if path == "/health/":
return 0.001
if re.match(r"/v1\/api\/some-path\/\S+\/$", path) and method == "GET":
return 0.001
if path == "/v1/api/token/":
return 0.001
return 1
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[DjangoIntegration()],
send_default_pii=True,
traces_sampler=traces_sampler,
profiles_sample_rate=1.0,
environment=SENTRY_ENV,
) |
thanks @omerfarukabaci, just to rule another possibility out first, you are setting the Authentication middleware like this too before the OTP one right? # "settings.py"
MIDDLEWARE = [
...
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django_otp.middleware.OTPMiddleware' # Here
] |
Heyt @sl0thentr0py, you're welcome! Yes, it is set as following: MIDDLEWARE = [
...
"django.contrib.auth.middleware.AuthenticationMiddleware",
("django_otp.middleware.OTPMiddleware" if ROLE == "admin" else None),
] |
Thanks for helping us investigate, this is very much appreciated! ❤
This is sort of the direction I was thinking. One thing to test whether this has anything to do with the SDK accessing the user is to set |
You're welcome, it is my pleasure, and also thank you for your concern! ❤️ Unfortunately I am on vacation for 3 weeks, I will try that and let you know when I am back. 🚀 |
cc @Zylphrex can the cached frame somehow cause state race conditions in weird scenarios? |
To the best of my knowledge, no. This is because we only cache the extracted attributes of a frame meaning the actual frame object itself is not stored between sampling. One idea that might shed some light on this issue is to inject a middleware
to check if Perhaps something along the lines of import logging
LOGGER = logging.getLogger(__name__)
class LogIsVerifiedMiddleware:
def __init__(self, get_response=None):
self.get_response = get_response
def __call__(self, request):
user = getattr(request, 'user', None)
if user is None:
LOGGER.info("No user found")
else:
has_is_verified = hasattr(user, "is_verified")
if has_is_verified:
LOGGER.info("User has is_verified")
else:
LOGGER.info("User does not have is_verified")
return self.get_response(request) This will help confirm at which point the method disappears or if it was ever there. |
Hey @Zylphrex, thank you for your answer! 🚀 The middleware you have provided will cause lazy
If you look at I will again disable profiling for a while to make sure this is really a Sentry issue. |
Thanks @omerfarukabaci, let us know once you have more info |
Hey @szokeasaurusrex, Sentry profiling has been disabled for the last 4 days, and the issue has gone away again. We have one other issue that appeared after enabling profiling, I didn't mention it previously because I wasn't sure that if it is related with Sentry or not, but now looking at the stack trace in detail, it is stemming from the Sentry source code for profiling, and looks like it has something to do with lazy At the end this causes an error in MySQL: Looking at the above stack trace, I am pretty sure that Sentry profiling is evaluating the lazy Sorry for not bringing up this issue previously, I didn't see (or forgot) that it is from a Sentry thread. 🙂 🚀 |
@omerfarukabaci The link would be helpful :) |
@szokeasaurusrex Can I send it through email, if so can you share an email that I can send it to? I don't want to expose our Sentry URL, just in case. 🙂 Also, one other important thing I have realized is that, if you look at the stack trace you can see the attribute being get is from django.utils.functional import SimpleLazyObject
def get_user():
print("evaluated")
user = User.objects.first()
return user
lazy_user = SimpleLazyObject(lambda: get_user())
lazy_user.__class__ # prints "evaluated" After a quick research, I found out that the only part that does something with |
Yep I think that's it, good find! :) The problem is this line which is a property so the underlying object will be evaluated. I talked to @Zylphrex and we will replace this
|
@sl0thentr0py Amazing, thank you all for your help from the beginning till the end! 🚀 Please let me know when a new version is released, so that I can upgrade to the latest and test if this was the actual problem. 😇 |
#3716 contains the fix we discussed. Thank you for patience 🙏 |
Closing, since this should be fixed by #3716. |
It's been ~5 days since I have upgraded I confirm that this issue is resolved, thank you all for your help! 🚀 |
Thanks for confirming @omerfarukabaci and helping us fix this! |
Environment
SaaS (https://sentry.io/)
Steps to Reproduce
Versions:
Django
: 4.2.15uwsgi
: 2.0.24sentry-sdk
: 2.13.0django-otp
: 1.5.1Setup
django-otp
: https://django-otp-official.readthedocs.io/en/stable/overview.html#installationUse
django_otp.admin.OTPAdminSite
as custom admin site.Enable profiling by setting
profiles_sample_rate
insentry_sdk.init
.When the
uwsgi
server starts, the first request to the admin fails with the error:'User' object has no attribute 'is_verified'
If you remove the
profiles_sample_rate
fromsentry_sdk.init
, the error goes away.Expected Result
Profiling should not change the behaviour of middleware so I would expect
django_otp.middleware.OTPMiddleware
to set theis_verified
attribute on theUser
object successfully.Actual Result
django_otp.middleware.OTPMiddleware
somehow cannot setUser.is_verified
for the first request in the admin. Consequent calls works fine, but only the initial request to admin fails.Product Area
Profiling
Link
No response
DSN
No response
Version
No response
The text was updated successfully, but these errors were encountered: