Zodbverify debugging

Trying to delete a page with id "foobar_2013" results in a PicklingError for a class that is no longer part of the buildout. Running zodbverify, I was able to find a reference to it.

```
Could not process <class 'z3c.relationfield.relation.RelationValue'> record '\x00\x00\x00\x00\x00\x03\xf4\x1e':
INFO:zodbverify:'cz3c.relationfield.relation\nRelationValue\nq\x01.}q\x02(U\x05to_idq\x03NU\x08_from_idq\x04J\xb9w\xfd\x0fU\x0efrom_attributeq\x05U\risReferencingq\x06U\n__parent__q\x07(U\x08\x00\x00\x00\x00\x00\x03\xfe\x1dcProducts.DecisionLog.content\nDecision\nq\x08tq\tQU\x0f_broken_to_pathq\nU\x1dfoobar-2013_MIGRATION_q\x0bu.'
INFO:zodbverify:Traceback (most recent call last):
  File "/sprj/st_zope_plone5/buildouts/eggs/zodbverify-1.0.2-py2.7.egg/zodbverify/verify.py", line 60, in verify_record
    unpickler.load()
ImportError: No module named DecisionLog.content

    0: }    EMPTY_DICT
    1: q    BINPUT     2
    3: (    MARK
    4: U        SHORT_BINSTRING 'to_id'
   11: q        BINPUT     3
   13: N        NONE
   14: U        SHORT_BINSTRING '_from_id'
   24: q        BINPUT     4
   26: J        BININT     268269497
   31: U        SHORT_BINSTRING 'from_attribute'
   47: q        BINPUT     5
   49: U        SHORT_BINSTRING 'isReferencing'
   64: q        BINPUT     6
   66: U        SHORT_BINSTRING '__parent__'
   78: q        BINPUT     7
   80: (        MARK
   81: U            SHORT_BINSTRING '\x00\x00\x00\x00\x00\x03\xfe\x1d'
   91: c            GLOBAL     'Products.DecisionLog.content Decision'
  130: q            BINPUT     8
  132: t            TUPLE      (MARK at 80)
  133: q        BINPUT     9
  135: Q        BINPERSID
  136: U        SHORT_BINSTRING '_broken_to_path'
  153: q        BINPUT     10
  155: U        SHORT_BINSTRING 'foobar-2013_MIGRATION_'
  186: q        BINPUT     11
  188: u        SETITEMS   (MARK at 3)
  189: .    STOP
highest protocol among opcodes = 1
> /sprj/st_zope_plone5/buildouts/eggs/zodbverify-1.0.2-py2.7.egg/zodbverify/verify.py(79)verify_record()
-> msg = "{}: {}".format(e.__class__.__name__, str(e))
```

The "foobar-2013_MIGRATION_" name gives a hint that this is from Products.contentmigration when migrating from 4.x to 5.0. We're now on 5.1.5. So I have the oid, how can I remove it? app._p_jar['\x00\x00\x00\x00\x00\x03\xfe\x1d'] gives a key error.

I do see this in the zc.relation catalog, but I'm unable to remove it.

>>> rel.from_path
''
>>> rel.to_path
'acrylonitrile-2013_MIGRATION_'
>>> catalog.unindex(rel)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/sprj/st_zope_plone5/buildouts/eggs/zc.relation-1.0-py2.7.egg/zc/relation/catalog.py", line 546, in unindex
    self.unindex_doc(self._relTools['dump'](rel, self, {}))
  File "/sprj/st_zope_plone5/buildouts/eggs/z3c.relationfield-0.7-py2.7.egg/z3c/relationfield/index.py", line 13, in dump
    return intids.getId(obj)
  File "/sprj/st_zope_plone5/buildouts/eggs/five.intid-1.1.2-py2.7.egg/five/intid/intid.py", line 41, in getId
    return z3IntIds.getId(self, ob)
  File "/sprj/st_zope_plone5/buildouts/eggs/zope.intid-3.7.2-py2.7.egg/zope/intid/__init__.py", line 89, in getId
    raise KeyError(ob)
KeyError: <z3c.relationfield.relation.RelationValue object at 0x7f79af5a1de8>
>>>

I think I can actually just rebuild the relation catalog. So although it would be nice to know how to deal with an obj given its oid, it doesn't appear to be needed for this case.

relations = catalog.findRelations()
catalog.clear()
for relation in relations:
   try:
     catalog.index(relation)
   except KeyError:
     pass

You would need to edit the objects referencing the broken object (and remove the reference). You cannot simply overwrite the broken object as the references contain the class information (for this reason, the class of a persistent object cannot be changed).

Plone Foundation Code of Conduct