ausaccessfed/virtualhome — pull request #166 by bradleybeddoes (2014-05-05 01:52:27+00:00)
Title: Accounts can get into an error state where they can no longer log in

Bug manifested as a 500 error upon entering two-step code during auth. Other users were able to log in fine. Restart did not correct the issue.

Entries from the `two_step_session` table (stripped + anonymized):

+----+---------+---------------------+--------------------+--------------------------------------+
| id | version | expiry | managed_subject_id | value |
+----+---------+---------------------+--------------------+--------------------------------------+
| 12 | 0 | 2014-01-21 23:49:39 | 99999999 | nyTtTFMZFZZKz0YZ...X9RSW7H5s59QdfPyZ |
| 15 | 0 | 2014-01-21 23:50:21 | 99999999 | 9iMryiGgOJ3wU2eb...xKQftdKzHAU656VOJ |
| 24 | 0 | 2014-01-22 00:09:53 | 99999999 | kZs1ToRB9p9wjVOE...emc6STdAXUFkhKZaX |
| 30 | 0 | 2014-02-09 22:32:40 | 99999999 | hxKGKmkBVecKArsv...iQ5LWrRv2I6honHP3 |
| 33 | 0 | 2014-02-11 05:13:59 | 99999999 | VTaYcTfCiiTaqhYq...ykMwcoszJPS0FXVey |
+----+---------+---------------------+--------------------+--------------------------------------+

This occurred on the morning of 2014-04-22, which coincides with the expiry of three entries here.

Attempting to log in caused the following exception:

[ 22.04.14 11:47:44.780] ERROR StackTrace - Full Stack Trace:
org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [aaf.vhr.TwoStepSession#15]
at org.hibernate.impl.SessionImpl.forceFlush(SessionImpl.java:1230)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:188)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor.onSaveOrUpdate(ClosureEventTriggeringInterceptor.java:108)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:685)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:677)
at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:252)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154)
at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:387)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at aaf.vhr.LoginService$$EnhancerByCGLIB$$fc5394c1.twoStepLogin()
at aaf.vhr.LoginService$twoStepLogin.call(Unknown Source)
at aaf.vhr.LoginController.twosteplogin(LoginController.groovy:109)
at aaf.vhr.LoginController.twosteplogin(LoginController.groovy)

Clearing the `two_step_session` entries for the user in question resolved the problem.

Best guess is you can't add and delete objects from the same association during a single transaction? Really not sure how this is handled by GORM.

![](http://i.imgur.com/8q4w9Sf.jpg)