Monday, February 1, 2010

Fixing PosKey Errors in Zope

Update: For a possibly easier way to _find_ PosKey errors, look here: http://www.zopyx.de/blog/checking-your-zodb-storages-for-poskey-errors

Some objects in my Plone site were broken: when clearing and rebuilding the catalog, i saw "PosKey" errors in my Zope logfile (*). Which objects are broken, and what to do about it?

I put a pdb statement in the file which caused errors, which was CMFCore/CatalogTool.py, line 390:

+ try:
+ dummy = base_hasattr(obj, 'indexObject')
+ except:
+ import pdb; pdb.set_trace()

I re-ran the catalog rebuild and was dropped into a pdb shell:

> from Acquisition import aq_parent
> parent = aq_parent(obj)

This showed which folderish thing contained the broken object.

Stopping the pdb session (using c, continue with the program) and looking in the ZMI, i was able to see that these objects were indeed broken: They could not be viewed in the ZMI (the same PosKey error).

Luckily, you can start Zope in debug mode for this, so it's Zope debug to the rescue:

$ ./client0/bin/zopectl debug # yep, a Plone 2.5 site
> site = getattr(app, 'my-sites-id-in-zope')
> folder = site.somefolder
> delattr(folder,'my-broken-object')
> import transaction; transaction.commit()


Broken object is thrown away: Problem solved. You can now clear and rebuild the catalog, and there will be much rejoicing.

If something in your site depends in the object being there, most likely with a special id, you could re-create the object from the Zope debug console like this:

> from Products.SomeProduct.content.SomeContentType import SomeContentType
> id = 'special-id' # use an id that's unique in the folder
> recreated_object = SomeContentType(id)
> folder.special-id = recreated_object
> import transaction; transaction.commit()


(*) The question remains, how object get "broken" in this manner. Anyone willing to shed light on this is very welcome to reply.

No comments: