[SOLVED] Restapi upload in 6.1.1 vs earlier versions, bug?

I can do:

curl -i -X POST https://mysite -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"@type": "Document", "title": "My Document"}' --user admin:admin

on a Plone 6.0 site, but when I try the same on a (develop) 6.1.1 site without any add-ons installed, I get:

  TTP/1.1 500 Internal Server Error
  Date: Wed, 11 Jun 2025 20:59:59 GMT
  Server: waitress
  Content-Length: 2137
  Content-Type: application/json
  Location: https://mysitet.com/my-document
  Via: waitress
  X-Frame-Options: SAMEORIGIN
  X-Powered-By: Zope (www.zope.dev), Python (www.python.org)
  Connection: close

  {
    "message": "'bool' object has no attribute 'items'",
    "traceback": [
      "File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/ZPublisher/WSGIPublisher.py\", line 181, in transaction_pubevents",
      "    yield",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/ZPublisher/WSGIPublisher.py\", line 390, in publish_module",
      "    response = _publish(request, new_mod_info)",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/ZPublisher/WSGIPublisher.py\", line 284, in publish",
      "    result = mapply(obj,",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/ZPublisher/mapply.py\", line 98, in mapply",
      "    return debug(object, args, context)",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/ZPublisher/WSGIPublisher.py\", line 68, in call_object",
      "    return obj(*args)",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/plone/rest/service.py\", line 21, in __call__",
      "    return self.render()",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/plone/restapi/services/__init__.py\", line 19, in render",
      "    content = self.reply()",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/plone/restapi/services/content/add.py\", line 116, in reply",
      "    serialized_obj = serializer()",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/plone/restapi/serializer/dxcontent.py\", line 127, in __call__",
      "    result.update(expandable_elements(self.context, self.request))",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/plone/restapi/serializer/expansion.py\", line 23, in expandable_elements",
      "    update_dict_recursively(res, element[1](expand=False))",
      "",
      "  File \"/home/plone/mysite_8080/venv/lib/python3.10/site-packages/plone/restapi/serializer/expansion.py\", line 28, in update_dict_recursively",
      "    for key, value in u.items():"
    ],
    "type": "AttributeError"
curl -i -X POST https://classic.demo.plone.org/en -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"@type": "Document", "title": "My Document"}' --user admin:admin

works like expected on the demo site. any other customization on your site?

No, the site is 'fresh', but I have products in eggs that are not installed.
That said: I had the same add-ons in Plone 6.0 so that is a bit weird.

So it probably means that some add-on can 'produce this error' even if it is not installed (?)

If an add’on doesn’t use a browserlayer in the backend that checks if the add’on was activated in the Plone site, yes.

On startup, the zcml in every addom that installed on the filesystem and ‘findable by Zope/Plone, will be evaluated.

But please: can you move those extra add’on out of the project and test if it resolves your problem? It could still be something else as well.

Quick test:

docker run --rm -e SITE="Plone" -e PROFILES="plone.restapi:default" -p 8080:8080 plone/plone-backend:6.1 start
curl --noproxy '*' -i -X POST http://localhost:8080/Plone -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"@type": "Document", "title": "My Document"}' --user admin:admin

open your browser and call http://localhost:8080/Plone and login via admin/admin. you should see your created content via restapi call.

Thanks, that was the case:

I narrowed it down, it turns out one of the add-ons has a restapi_service, which did not include the following:

if not expand:
    return result

Off topic:

Is it possible to limit <plone:service to a browserlayer ?

Not working, is there another way:

  <plone:service
layer="my.addon.interfaces.IMyLayer"

you can check the existence of browserlayer in your service

from plone.browserlayer import utils
from your.addon.interfaces import IYourAddonBrowserLayer

class YourService(Service):
    def reply(self):
        if IYourAddonBrowserLayer not in utils.registered_layers():
            raise an error
      ....
1 Like