[reported to Collector; posted as FYI] Under certain circumstances, Zope transaction objects will have their abort() method called more than once for the same transaction, which leads to jar.abort() operations being called twice. This occurs any time that the zpublisher_exception_hook reraises the original exception, such as if the exception is an 'unauthorized' or 'redirect', or if a standard_error_message handler can't be found, or the transaction is being executed by XML-RPC or some other non-HTML protocol. Under "normal" circumstances (most other errors), the transaction's abort() method is *still* called twice, but with different arguments that lead to registered objects being aborted only once. This is a mess, because to write objects which can be registered with a transaction, one must consider the possibility of being aborted twice during the same transaction. It appears that the Zope exception hook uses get_transaction.begin() in order to do an abort. If it first did an abort(), this would at least make the double-abort behavior consistent. :) In practice, it seems as though it would be better to avoid double aborts by always having the abort method clear/reset self._objects. (The second abort takes place as a result of the __del__ method being called while there are still registered objects, following the free_transaction() called in the first execution of abort(). (Are you confused yet?) To add to the interestingness of this situation, there is a method which releases cached connection objects associated with the transaction, in collaboration with ZODB.DB.open(). This collaborating pair looks completely broken, as it assumes only a single DB exists, and also the method only ends up called by aborts, not commits. It does not appear as though anything in Zope uses this mechanism currently, but it should probably be fixed or removed before somebody hurts themselves with it. :)