Conflict error and "Could not adapt" error with Volto and Plone 5.2

Hi folks,
We are running into two errors since we are using Plone 5.2 with Volto. In fact they are not reproduceable using Classic UI, so I would lean more on the p.restapi interface to be who to point to, at least for now. They are not reproduceable in 5.1 (with p.restapi) in any case too, so that narrows (or confuses) a little bit more the case.

This is the conflict error:

2019-12-04 10:50:46,006 ERROR   [ZODB.ConflictResolution:294][waitress] Unexpected error while trying to resolve conflict on <class 'collective.folderishtypes.dx.content.FolderishDocument'>
Traceback (most recent call last):
  File "/Users/sneridagh/Development/eggs/ZODB-5.5.1-py3.7.egg/ZODB/ConflictResolution.py", line 262, in tryToResolveConflict
    resolve = inst._p_resolveConflict
  File "/Users/sneridagh/Development/eggs/plone.dexterity-2.9.1-py3.7.egg/plone/dexterity/content.py", line 735, in __getattr__
    return CMFOrderedBTreeFolderBase.__getattr__(self, name)
  File "/Users/sneridagh/Development/eggs/Products.BTreeFolder2-4.2-py3.7.egg/Products/BTreeFolder2/BTreeFolder2.py", line 240, in __getattr__
    return self._tree[name]
TypeError: 'NoneType' object is not subscriptable
2019-12-04 10:50:46,869 ERROR   [Zope.SiteErrorLog:251][waitress] 1575453046.8687890.5727237784649776 http://localhost:8080/Plone/de/dummy/asdasdas/GET_application_json_
Traceback (innermost last):
  Module ZPublisher.WSGIPublisher, line 161, in transaction_pubevents
  Module transaction._manager, line 252, in commit
  Module transaction._manager, line 131, in commit
  Module transaction._transaction, line 311, in commit
  Module transaction._compat, line 50, in reraise
  Module transaction._transaction, line 302, in commit
  Module transaction._transaction, line 447, in _commitResources
  Module transaction._compat, line 50, in reraise
  Module transaction._transaction, line 421, in _commitResources
  Module ZODB.Connection, line 497, in commit
  Module ZODB.Connection, line 546, in _commit
  Module ZODB.Connection, line 602, in _store_objects
  Module ZODB.mvccadapter, line 165, in store
  Module ZODB.FileStorage.FileStorage, line 603, in store
  Module ZODB.ConflictResolution, line 297, in tryToResolveConflict
ZODB.POSException.ConflictError: database conflict error (oid 0x09f03c, class collective.folderishtypes.dx.content.FolderishDocument, serial this txn started with 0x03d43c9712bdc533 2019-12-03 15:51:04.392490, serial currently committed 0x03d440cea634b400 2019-12-04 09:50:38.954501)

We are using collective.folderishtypes addon to make all content types folderish.

The second error is:

2019-12-04 10:52:44,400 ERROR   [Zope.SiteErrorLog:251][waitress] 1575453164.4001880.27303118517455216 http://localhost:8080/Plone/de/dummy/asdasdas/GET_application_json_
Traceback (innermost last):
  Module ZPublisher.WSGIPublisher, line 155, in transaction_pubevents
  Module ZPublisher.WSGIPublisher, line 337, in publish_module
  Module ZPublisher.WSGIPublisher, line 255, in publish
  Module ZPublisher.mapply, line 85, in mapply
  Module ZPublisher.WSGIPublisher, line 61, in call_object
  Module plone.rest.service, line 23, in __call__
  Module plone.restapi.services, line 21, in render
  Module plone.restapi.services.content.get, line 18, in reply
  Module plone.restapi.serializer.dxcontent, line 125, in __call__
  Module plone.restapi.serializer.dxcontent, line 83, in __call__
  Module plone.restapi.serializer.dxfields, line 28, in __call__
  Module plone.restapi.serializer.dxfields, line 31, in get_value
TypeError: ('Could not adapt', <FolderishDocument at /Plone/de/dummy>, <SchemaClass plone.restapi.behaviors.IBlocks>)

This last error is a Heisenbug, it's completely random and is gone on reload on the same failing object.

If it rings a bell to someone, it would be great to know what might be the cause.
Cheers,
V.

1 Like

I see this kind of weird errors when the iface identifier is used instead of the behavior name.
If you are using something like:


try replacing it with:

<element value="volto.blocks" />
1 Like

We are indeed using the iface. Wasn't that the preferred approach? I just saw that p.a.contenttypes has all of them in the behavior name form.

Thanks a lot! I will try your suggestion asap.

1 Like

@alert that seems have did the trick... man you're my saviour lately :slight_smile: I owe you a beer!

I will keep you posted about the outcome, but it looks good so far.
Thanks!!

2 Likes

No, using the name is the preferred way. I tend to fade out using the interface here by logging deprecation warnings. Your Heisenbug strengthens my opinion here.

3 Likes

Should/could we in P6 kill the fallback?

1 Like

Yes, that's a plan. I would second a Plip, would you write it?

1 Like

Help me with https://github.com/plone/Products.CMFPlone/issues/2454 by figuring out/fixing https://jenkins.plone.org/view/PLIPs/job/plip-dx-siteroot-3.7/19/testReport/junit/plone.app.contentrules.tests.test_action_versioning/TestVersioningAction/testExecute/ , and I'll add a PLIP for removing the fallback behavior lookup mechanism.

3 Likes

Regarding the failing test, it seems you are missing the call to an init method:

CMFOrderedBTreeFolderBase.__init__(obj, obj.getId(), obj.title)

More details http://blog.redturtle.it/2013/02/25/migrating-dexterity-items-to-dexterity-containers, look for _tree.
If I am able I will give this a try myself.

2 Likes

You could join us remotely for the Plone 6 Kick-Off sprint tomorrow. :slight_smile:

Just to have it written somewhere, we've noticed that there are still places that the old interface name is still used, mainly in tests:

for p.a.dexterity, p.a.event, plone.api, p.restapi.

FYI: @jensens helped us track down and fix the problem:

Thank you Jens!

3 Likes

FYI: plone.dexterity 2.9.3 released with the fix: https://pypi.org/project/plone.dexterity/2.9.3/#id1

2 Likes

@jaroel @jensens I just ran into this nasty bug again. Do you still wanna write that PLIP? :slight_smile:

I would like to see at least a warning to show up on this in Plone 5.2. It is easy to forget about this and the consequences are really nasty.

I run into an odd behavior of a behavior. The behavior is quite simple, it is just extending the ILeadImage with an additional copyright field:

class ILeadImageCopyright(ILeadImage):
    pass


@provider(IFormFieldProvider)
class ILeadImageCopyrightBehavior(ILeadImageBehavior):
    copyright = schema.TextLine(title="Lead image copyright", required=False)


@adapter(IDexterityContent)
@implementer(ILeadImageCopyrightBehavior)
class LeadImageCopyright(LeadImage):

    @property
    def copyright(self):
        return self.context.copyright

    @copyright.setter
    def copyright(self, value):
        self.context.copyright = value

It is registered for Documents and works using Classic UI and Plone 6.0.13. The News Item type also works without any errors on the frontend.

However in the test layer it caused some unexpected "damage". The test case where I have:

    def test_news_item_create_no_image(self):
        with api.env.adopt_roles('Manager'):
            api.content.create(type='News Item', container=self.portal, title='test')
        ...

It produces the following traceback:

Error in test test_news_item_create (collective.foobar.tests.test_setup.TestSetup.test_news_item_create)
Traceback (most recent call last):
  File "/usr/lib/python3.11/unittest/case.py", line 57, in testPartExecutor
    yield
  File "/usr/lib/python3.11/unittest/case.py", line 623, in run
    self._callTestMethod(testMethod)
  File "/usr/lib/python3.11/unittest/case.py", line 579, in _callTestMethod
    if method() is not None:
  File "/home/user/collective.foobar/src/collective/foobar/tests/test_setup.py", line 45, in test_news_item_create
    api.content.create(type='News Item', container=self.portal, title='test')
  File "/home/user/.buildout/eggs/cp311/decorator-5.1.1-py3.11.egg/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/home/user/.buildout/eggs/cp311/plone.api-2.2.2-py3.11.egg/plone/api/validation.py", line 73, in wrapped
    return function(*args, **kwargs)
  File "/home/user/.buildout/eggs/cp311/decorator-5.1.1-py3.11.egg/decorator.py", line 232, in fun
    return caller(func, *(extras + args), **kw)
  File "/home/user/.buildout/eggs/cp311/plone.api-2.2.2-py3.11.egg/plone/api/validation.py", line 149, in wrapped
    return function(*args, **kwargs)
  File "/home/user/.buildout/eggs/cp311/plone.api-2.2.2-py3.11.egg/plone/api/content.py", line 73, in create
    container.invokeFactory(type, content_id, **kwargs)
  File "/home/user/.buildout/eggs/cp311/plone.dexterity-3.0.6-py3.11.egg/plone/dexterity/content.py", line 815, in invokeFactory
    return super().invokeFactory(type_name, id, RESPONSE, *args, **kw)
  File "/home/user/.buildout/eggs/cp311/Products.CMFCore-3.5-py3.11.egg/Products/CMFCore/PortalFolder.py", line 299, in invokeFactory
    return ttool.constructContent(type_name, self, id, RESPONSE,
  File "/home/user/.buildout/eggs/cp311/Products.CMFCore-3.5-py3.11.egg/Products/CMFCore/TypesTool.py", line 807, in constructContent
    ob = info.constructInstance(container, id, *args, **kw)
  File "/home/user/.buildout/eggs/cp311/Products.CMFCore-3.5-py3.11.egg/Products/CMFCore/TypesTool.py", line 306, in constructInstance
    return self._constructInstance(container, id, *args, **kw)
  File "/home/user/.buildout/eggs/cp311/Products.CMFCore-3.5-py3.11.egg/Products/CMFCore/TypesTool.py", line 568, in _constructInstance
    rval = container._setObject(id, obj)
  File "/home/user/.buildout/eggs/cp311/Products.BTreeFolder2-5.1-py3.11.egg/Products/BTreeFolder2/BTreeFolder2.py", line 463, in _setObject
    notify(ObjectAddedEvent(ob, self, id))
  File "/home/user/.buildout/eggs/cp311/zope.event-5.0-py3.11.egg/zope/event/__init__.py", line 33, in notify
    subscriber(event)
  File "/home/user/.buildout/eggs/cp311/zope.component-6.0-py3.11.egg/zope/component/event.py", line 27, in dispatch
    component_subscribers(event, None)
  File "/home/user/.buildout/eggs/cp311/zope.component-6.0-py3.11.egg/zope/component/_api.py", line 146, in subscribers
    return sitemanager.subscribers(objects, interface)
  File "/home/user/.buildout/eggs/cp311/zope.interface-6.3-py3.11-linux-x86_64.egg/zope/interface/registry.py", line 446, in subscribers
    return self.adapters.subscribers(objects, provided)
  File "/home/user/.buildout/eggs/cp311/zope.interface-6.3-py3.11-linux-x86_64.egg/zope/interface/adapter.py", line 896, in subscribers
    subscription(*objects)
  File "/home/user/.buildout/eggs/cp311/zope.component-6.0-py3.11.egg/zope/component/event.py", line 37, in objectEventNotify
    component_subscribers((event.object, event), None)
  File "/home/user/.buildout/eggs/cp311/zope.component-6.0-py3.11.egg/zope/component/_api.py", line 146, in subscribers
    return sitemanager.subscribers(objects, interface)
  File "/home/user/.buildout/eggs/cp311/zope.interface-6.3-py3.11-linux-x86_64.egg/zope/interface/registry.py", line 446, in subscribers
    return self.adapters.subscribers(objects, provided)
  File "/home/user/.buildout/eggs/cp311/zope.interface-6.3-py3.11-linux-x86_64.egg/zope/interface/adapter.py", line 896, in subscribers
    subscription(*objects)
  File "/home/user/.buildout/eggs/cp311/plone.app.versioningbehavior-2.0.3-py3.11.egg/plone/app/versioningbehavior/subscribers.py", line 112, in create_initial_version_after_adding
    context.portal_repository.save(obj=context, comment=changeNote)
  File "/home/user/.buildout/eggs/cp311/Products.CMFEditions-4.0.3-py3.11.egg/Products/CMFEditions/CopyModifyMergeRepositoryTool.py", line 301, in save
    self._recursiveSave(
  File "/home/user/.buildout/eggs/cp311/Products.CMFEditions-4.0.3-py3.11.egg/Products/CMFEditions/CopyModifyMergeRepositoryTool.py", line 456, in _recursiveSave
    prep = portal_archivist.prepare(obj, app_metadata, sys_metadata)
  File "/home/user/.buildout/eggs/cp311/Products.CMFEditions-4.0.3-py3.11.egg/Products/CMFEditions/ArchivistTool.py", line 266, in prepare
    referenced_data = modifier.getReferencedAttributes(obj)
  File "/home/user/.buildout/eggs/cp311/Products.CMFEditions-4.0.3-py3.11.egg/Products/CMFEditions/ModifierRegistryTool.py", line 134, in getReferencedAttributes
    for name, attrs in mod.getReferencedAttributes(obj).items():
  File "/home/user/.buildout/eggs/cp311/plone.app.versioningbehavior-2.0.3-py3.11.egg/plone/app/versioningbehavior/modifiers.py", line 118, in getReferencedAttributes
    field_value = field.get(field.interface(obj))
TypeError: ('Could not adapt', <NewsItem at /plone/20107233>, <SchemaClass plone.app.contenttypes.behaviors.leadimage.ILeadImageBehavior>)

The odd thing, that in modifiers.py at the given line say the obj provides ILeadImage marker, but it can not adapt the ILeadImageBehavior.

The News Item create test works as soon as:

  • The behavior registration is removed.
  • The behavior schema is not based on ILeadImageBehavior.

The same behavior worked on Plone 5.2 using the pre plone.app.contenttypes commit de4495 changes.

Is it related to what has been discussed in this topic? What am I missing here? Or behaviors can not be sub-classed?

Note: I've tested it with a clean plone.bobtemplate generated collective.foobar too, to make sure the error is reproducible. The buildout runs on Plone 6.0.13 and the single change is, that I've registered the modified behavior for Document type. As soon as that happens, the error is present in the test layer for News Item create.