Mikko Ohtamaa
Mikko Ohtamaa

Reputation: 83676

Plone: TypeError: Can't pickle objects in acquisition wrappers

I am using / fixing collective.logbook to save errors on the site. Currently logbook fails on my site on some exceptions:

  File "/srv/plone/xxx/src/collective.logbook/collective/logbook/events.py", line 101, in hand
    transaction.commit()
  File "/srv/plone/buildout-cache/eggs/transaction-1.1.1-py2.6.egg/transaction/_manager.py", line 8
    return self.get().commit()
  File "/srv/plone/buildout-cache/eggs/transaction-1.1.1-py2.6.egg/transaction/_transaction.py", li
    self._commitResources()
  File "/srv/plone/buildout-cache/eggs/transaction-1.1.1-py2.6.egg/transaction/_transaction.py", li
    rm.commit(self)
  File "/srv/plone/buildout-cache/eggs/ZODB3-3.10.5-py2.6-linux-x86_64.egg/ZODB/Connection.py", lin
    self._commit(transaction)
  File "/srv/plone/buildout-cache/eggs/ZODB3-3.10.5-py2.6-linux-x86_64.egg/ZODB/Connection.py", lin
    self._store_objects(ObjectWriter(obj), transaction)
  File "/srv/plone/buildout-cache/eggs/ZODB3-3.10.5-py2.6-linux-x86_64.egg/ZODB/Connection.py", lin
    p = writer.serialize(obj)  # This calls __getstate__ of obj
  File "/srv/plone/buildout-cache/eggs/ZODB3-3.10.5-py2.6-linux-x86_64.egg/ZODB/serialize.py", line
    return self._dump(meta, obj.__getstate__())
  File "/srv/plone/buildout-cache/eggs/ZODB3-3.10.5-py2.6-linux-x86_64.egg/ZODB/serialize.py", line
    self._p.dump(state)
TypeError: Can't pickle objects in acquisition wrappers.

This is obviously because logbook tries to write a record of the error which refers to an acquired object. I assume that the solution is to clean the error from these kind of objects.

However, how can I figure out what is the bad object, how it ends up to the transaction manager and what are the Python object references causing this issue? Or anything which could help me to debug this issue?

Upvotes: 4

Views: 704

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124558

If you can reproduce this reliably, you can put in a print statement or pdb.set_trace() in the ZODB connection _register method (in ZODB/connection.py inside the ZODB egg):

def _register(self, obj=None):
    # ... skipped lines ...

    if obj is not None:
        self._registered_objects.append(obj)
        # Insert print statement here.

Now whenever any object has been marked as changed or is added to the connection as a new object, it'll be printed to the console. That should help you with the debugging process. Good luck!

Upvotes: 3

Related Questions