Diazo theme no longer working

Hello group,

I'm encountering an unexpected portal_transforms + diazo problem following an OS upgrade:

  • Plone version is 5.2.12 on Python 3.9.
  • OS version went from FreeBSD 13.3 to 13.5, and packages were updated accordingly (among which, libxml2 and libxslt).

As a result, lxml stopped working (couldn't find shared libxml2 libraries files).

I decided to rebuild the buildout. On my server, lxml 4.8.0 doesn't compile with the default compiler (clang / LLVM 19), but seems to compile with GCC 13. lxml 5.0.x, on the other hand, does compiles with clang.

Whatever the version, the theming engine no longer works for me:

2025-07-05 17:03:49,592 ERROR   [plone.transformchain:69][waitress-3] Unexpected error whilst trying to apply transform chain
Traceback (most recent call last):
  File "/usr/local/plone/buildout/buildout-cache/eggs/cp39/plone.transformchain-2.0.2-py3.9.egg/plone/transformchain/transformer.py", line 59, in __call__
    newResult = handler.transformIterable(result, encoding)
  File "/usr/local/plone/buildout/buildout-cache/eggs/cp39/plone.app.theming-4.1.8-py3.9.egg/plone/app/theming/transform.py", line 166, in transformIterable
    transform = self.setupTransform(runtrace=runtrace)
  File "/usr/local/plone/buildout/buildout-cache/eggs/cp39/plone.app.theming-4.1.8-py3.9.egg/plone/app/theming/transform.py", line 92, in setupTransform
    transform = compileThemeTransform(
  File "/usr/local/plone/buildout/buildout-cache/eggs/cp39/plone.app.theming-4.1.8-py3.9.egg/plone/app/theming/utils.py", line 717, in compileThemeTransform
    compiledTheme = compile_theme(
  File "/usr/local/plone/buildout/buildout-cache/eggs/cp39/diazo-2.0.1-py3.9.egg/diazo/compiler.py", line 127, in compile_theme
    rules_doc = process_rules(
  File "/usr/local/plone/buildout/buildout-cache/eggs/cp39/diazo-2.0.1-py3.9.egg/diazo/rules.py", line 300, in process_rules
    rules_doc = etree.parse(rules, parser=rules_parser)
  File "src/lxml/etree.pyx", line 3549, in lxml.etree.parse
  File "src/lxml/parser.pxi", line 1966, in lxml.etree._parseDocument
  File "src/lxml/parser.pxi", line 1992, in lxml.etree._parseDocumentFromURL
  File "src/lxml/parser.pxi", line 1895, in lxml.etree._parseDocFromFile
  File "src/lxml/parser.pxi", line 1214, in lxml.etree._BaseParser._parseDocFromFile
  File "src/lxml/parser.pxi", line 650, in lxml.etree._ParserContext._handleParseResultDoc
  File "src/lxml/parser.pxi", line 760, in lxml.etree._handleParseResult
  File "src/lxml/parser.pxi", line 687, in lxml.etree._raiseParseError
OSError: Error reading file '/++theme++my-theme/rules.xml': Invalid argument

In the manifest.cfg file of my theme, I've tried to change the value for "rules":

The module refusing these values is plone.app.theming.utils, despite its doc stating that it accepts URLs.

I've also tried upgrading Diazo (tried 1.5.0 and 2.0.0).

Would anyone have ideas about how to correct the problem?

Many thanks in advance,
Laurent.

Not sure if your problem is diazo, are you sure your theme is called my.theme ? Any rule diazo 'uses' should be avalable at that url. So if you can go to that url, it will not work (paste that url to your browser'

You're right, the theme is not really called "my-theme", I've just replaced the actual name before posting, to hide the site's name. rules.xml is visible from the browser. There are no ownership or permission issues on the files. The code has worked in production for 6 years.

The problem is with this Diazo code, called by plone.app.theming:

rules_doc = etree.parse('/++theme++my-theme/rules.xml', parser=rules_parser)

rules_parser is, I suppose, an instance of etree.XMLParser, but I need to check further, because it accepts neither filesystem paths, nor HTTP URLs. It is most likely instantiated in plone.app.theming, which enforces the restrictions.

I know this post is old but I had this issue earlier and when I searched I could not find the solution. I am posting the cause of my problem to help others in the future (including me).

My setup:
Plone 6.0.14
Classic UI

The error message:

File "src/lxml/parser.pxi", line 760, in lxml.etree._handleParseResult
File "src/lxml/parser.pxi", line 682, in lxml.etree._raiseParseError
OSError: Error reading file '/++theme++my-theme/rules.xml': Invalid argument

The issue was caused when I pip installed zpretty in my venv and lxml 6.0.0 was pulled as a dependency. The fix was to downgrade lxml to version 5.4.0 which is what my other similar projects used.

Thank you for the suggestion :slight_smile: after checking, I don't have zpretty anywhere. The Plone 5.2 buildout is pinning the lxml version at 4.8.0. I have tried to install the latest lxml (6.x), but it proved incompatible with Plone 5 and/or its dependencies, so I removed it. 4.8.0 and 4.9.0 don't compile anymore with my setup, 5.0.x seems to be ok. I think I have to look at plone.app.theming, I'll do it after my holidays.

Just a "me too". I have the same error.

OSError: Error reading file '/++theme++barceloneta/rules.xml': Invalid argument

FreeBSD/amd64 14.3-RELEASE-p1
Python 3.11
Plone 6.1.2
lxml-5.4.0
no zpretty

Thanks in advance.

I would try to verify the actual lxml library being used next. If you are using buildout and have omelette it is a simple:

ls -l  parts/omelette
...
lxml -> /home/user_name/code/my_site/venv/lib/python3.12/site-packages/lxml
...

This will tell you which module is actually being used by your site. In my case it's lxml from my venv which I know uses version 5.4.0

I would also check if my rules.xml is a valid xml and if the file is readable by the user running my site.

Thank you :slight_smile: i would like to insist that the buildout had been working for several years, before a minor OS update prompted me to rebuild it. Hence:

  • rules.xml is valid,
  • there are no file permission issues,
  • /++theme++barceloneta/rules.xml is accessible via a browser.

IMHO, there seems to be an "unholy" interaction between plone.app.theming (which creates the rules parser for diazo) and lxml.

1 Like

OK, after lots of trials (and lots of errors...), I have come up with a workaround which will have to do:

  • in my manifest.cfg: replace line rules = /++theme++/... with rules = {/full/path/of/my/rules.xml}
  • in plone/app/theming/utils.py, comment out line 686: parser.resolvers.add(FailingFileSystemResolver()), as this resolver prevents the use of filesystem paths for rules.

The node of the problem seems to be that:

  1. plone/app/theming/utils.py defines an etree.XMLParser with several resolvers, among which InternalResolver, which can correctly access my rules.xml given its absolute URL path (/++theme++/...),

  2. but in diazo/rules.py, line 293: rules_doc = etree.parse(rules, parser=rules_parser), the parser happily ignores its resolvers.

Apparently, if rules is a string, etree.parse will bypass the resolvers, so one suggestion is to parse StringIO(rules) instead (e.g. Document loading and URL resolving). I've tried it, no joy.

Conclusion: I haven't understood why the problem appeared out of the blue (has the behaviour of lxml changed between versions 4.8.0 and 5.0.2? I haven't found anything relevant in the changelog), and I can't reasonably spend more hours on the problem, especially if diazois a legacy technology, so I'll satisfy myself with the workaround.

Laurent.

1 Like

Good that you found a workaround.

I suspect the real issue is with lxml. Perhaps you are missing other required development libraries and lxml was not built properly. The version you used may not be compatible as well.

1 Like

As far as I know, I compile+install lxml the same way as I have always done, and apart from this problem arising earlier this month, it works perfectly. I have an up-to-date libxml2, and the "latest" libxslt (with double quotes because libxslt is no longer maintained, which may become a problem in the long term for lxml). Build generates no error messages or warnings.

The notion of "development libraries" is an abomination created by the Debian maintainers, who decided to distinguish e.g. between python3, python3-dev, python3-venv, ... when the Python foundation is releasing a single Python distribution containing everything, including the standard library, pip and venv. Same goes for libxml2 and libxslt. As I am on FreeBSD, which respects original software, the distinction is irrelevant, I have the complete packages installed.

But basically yes, it's an lxml problem. What I could try, is to make a static build (STATIC_DEPS=true)

install of Plone 6.0.14

mkdir /tmp/plone6014
cd  /tmp/plone6014
touch requirements.txt
touch constraints.txt
touch instance.yaml
# constraints.txt
-c https://dist.plone.org/release/6.0.14/constraints.txt
# requirements.txt
-c constraints.txt
Plone
plone.app.upgrade
cookiecutter
# instance.yaml
default_context:
  initial_user_name: "admin"
  initial_user_password: "admin"
  wsgi_listen: "localhost:8080"
  db_storage: "direct
python3 -m venv ./venv
./venv/bin/pip install -r requirements.txt
./venv/bin/cookiecutter -f --no-input --config-file instance.yaml https://github.com/plone/cookiecutter-zope-instance
./venv/bin/runwsgi -v instance/etc/zope.ini

open your Browser: http://localhost:8080

add a Plone Classic UI

Please check if your error is present in a plain Plone installation.

1 Like

AFAIK there is no replacement for Diazo in Plone Classic. I don't consider this a legacy technology. On the other hand, if parts of lxml stop being maintained, then this might cause problems for Plone Classic in the long run.

2 Likes

I've tried that, it fails with easy_install errors or parallel build errors (make -j6). I won't explore further.

What I did explore, on the other hand, was upgrading the buildout to lxml 5.4.0. In addition to pinning the version, it's necessary to add lxml[html_clean]in the "eggs" section of the buildout.cfg file. Result is identical to version 5.0.2, i.e. display is ok with the workaround, not ok without it.

Also, same results with lxml 6.0.0, provided you have installed the additional package (lxml_html_clean).

Disclaimer: I must confess I haven't seriously looked at Plone 6 yet. Migrating the site I'm working on from Plone 4 + Python 2 to Plone 5 + Python 3 was a huge work. The ZODB is now full of cruft from obsolete Python 2 / Plone 4 products, I haven't been able to clean it all. Lots of extra stuff was added, regarding the graphical layout, responsive HTML, and fun portlet stuff enabled by Diazo. The work spanned over one year, in 2020-2021. In those conditions, I'm not sure I would offer the client to migrate to Plone 6 if that represents a similar or greater amount of work.

I understand that the classic UI in Plone 6 is legacy, with Volto (React) being the recommended way to go. In my case, that would mean redeveloping the UI entirely. But maybe I'm wrong.

1 Like

Thank you Jan, I'll try what you suggest soon. It will be my first serious try at Plone 6.

1 Like

PS : my workaround causes an error to appear in the logs, but the theming still works:

2025-07-17 11:23:50,873 ERROR [plone.app.theming:192][waitress-3] Couldn't resolve /usr/local/plone/buildout/zeocluster/src/XYZ.theme/src/XYZ/theme/theme/index.html

PS2: I seem to have a character encoding problem now :((

Thank you. I followed your instruction on FreeBSD/amd64 14.3-RELEASE-p1 and Python 3.11, and tested with Plone 6.0.14 and 6.1.2.

Unfortunately, I got the same error in both cases:

OSError: Error reading file '/++theme++barceloneta/rules.xml': Invalid argument

maybe a FreeBSD specific issue? Debian/Ubuntu usually applies patches to fix problems to not well maintained libraries, maybe you can check if there's a patch that can help in FreeBSD.

1 Like