Skip to content
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

DetachedInstanceError on login #79

Open
Zitrax opened this issue Jul 18, 2016 · 5 comments
Open

DetachedInstanceError on login #79

Zitrax opened this issue Jul 18, 2016 · 5 comments

Comments

@Zitrax
Copy link

Zitrax commented Jul 18, 2016

This might be due to my setup, but I am not yet sure exactly why I see this so I am filing an issue.

The confusing part is that I see this on one machine but not the other, and I have not yet pinpointed the difference. Could be some setup/environment that is different - or simply some timing issue.

Anyway this happens consistently when I try to login:

Traceback (most recent call last):
  File "..\lib\site-packages\waitress\channel.py", line 338, in service
    task.service()
  File "..\lib\site-packages\waitress\task.py", line 169, in service
    self.execute()
  File "..\lib\site-packages\waitress\task.py", line 399, in execute
    app_iter = self.channel.server.application(env, start_response)
  File "..\lib\site-packages\pyramid\router.py", line 223, in __call__
    response = self.invoke_subrequest(request, use_tweens=True)
  File "..\lib\site-packages\pyramid\router.py", line 198, in invoke_subrequest
    response = handle_request(request)
  File "..\lib\site-packages\pyramid_debugtoolbar\toolbar.py", line 266, in toolbar_tween
    toolbar.process_response(request, response)
  File "..\lib\site-packages\pyramid_debugtoolbar\toolbar.py", line 87, in process_response
    panel.process_response(response)
  File "..\lib\site-packages\pyramid_debugtoolbar\panels\request_vars.py", line 112, in process_response
    extracted_attributes = extract_request_attributes(self.request)
  File "..\lib\site-packages\pyramid_debugtoolbar\panels\request_vars.py", line 56, in extract_request_attributes
    if not hasattr(request, attr_):
  File "..\lib\site-packages\pyramid\security.py", line 344, in authenticated_userid
    return policy.authenticated_userid(self)
  File "..\lib\site-packages\pyramid\authentication.py", line 90, in authenticated_userid
    callback_ok = self.callback(userid, request)
  File "..\lib\site-packages\pyramid_fullauth\auth.py", line 28, in groupfinder
    if user and user.id == userid:
  File "..\lib\site-packages\sqlalchemy\orm\attributes.py", line 237, in __get__
    return self.impl.get(instance_state(instance), dict_)
  File "..\lib\site-packages\sqlalchemy\orm\attributes.py", line 578, in get
    value = state._load_expired(state, passive)
  File "..\lib\site-packages\sqlalchemy\orm\state.py", line 474, in _load_expired
    self.manager.deferred_scalar_loader(self, toload)
  File "..\lib\site-packages\sqlalchemy\orm\loading.py", line 610, in load_scalar_attributes
    (state_str(state)))
sqlalchemy.orm.exc.DetachedInstanceError: Instance <User at 0x497af10> is not bound to a Session; attribute refresh operation cannot proceed

so apparently the request.user instance is no longer bound to a session. Was it closed too early ?

Adding these lines to groupfinder() in auth.py:

    if user:
        from sqlalchemy.orm.session import object_session
        object_session(user).refresh(user)

right before the user variable is used reattaches it and all seem to work fine. Possibly there could also be a check to only use refresh if really needed.

However, I am not sure why I am even seeing this problem. Any idea ?

@Zitrax
Copy link
Author

Zitrax commented Jul 19, 2016

The workaround above still failed in some cases, where object_session returned None.

Another seemingly more reliable version of avoiding that exception is to change the implementation of user(request) in request.py to:

    if request.unauthenticated_userid:
        try:
            user = pyramid_basemodel.Session.query(User).filter(
                User.id == request.unauthenticated_userid
            ).options(joinedload('groups')).one()
            pyramid_basemodel.Session.expunge(user)
            return user
        except NoResultFound:  # pragma: no cover
            pass

The call to expunge to make sure the user object can be used even if detached, and the joinedload of groups since we access that too.

@fizyk
Copy link
Owner

fizyk commented Jul 19, 2016

Okay, it looks like it fails on the first request to load?
What's your session configuration? I have to admit It's the place I'd expect this to happen the least.

@Zitrax
Copy link
Author

Zitrax commented Jul 20, 2016

I am importing Session from pyramid_basemodel.

I noticed one machine was on pyramid 1.6.1 and the other 1.7. But updating that made no difference.

@Zitrax
Copy link
Author

Zitrax commented Jul 20, 2016

I did notice that the traceback contained pyramid_debugtoolbar and indeed turning that off removed the problem. Turns out with that enabled groupfinder() is called twice and fails with the exception the the second time.

@fizyk
Copy link
Owner

fizyk commented Jul 20, 2016

Okay then... this should not have happened... groupfinder doesn't have much in it to justify such behaviour. and neither does request.user.... You're using transactions package, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants