Error while viewing course units in studio for Open edX v21 Ulmo

After upgrading from Teak to Ulmo we are facing the following issue when while viewing course units in studio:

screenshot-course-unit-error-2026.01.26-10_19_21

The cms logs reveal that there is an issue with html_clean of lxml:

2026-01-26 09:23:59,125 ERROR 10 [django.request] log.py:253 - Internal Server Error: /api/contentstore/v1/container_handler/block-v1:XXXX+TC01+2026+type@vertical+block@9b78335c044a4c2abff12c0e477b4cfc
Traceback (most recent call last):
  File "/openedx/venv/lib/python3.11/site-packages/pkg_resources/__init__.py", line 2805, in requires
    deps.extend(dm[safe_extra(ext)])
                ~~^^^^^^^^^^^^^^^^^
KeyError: 'html_clean'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/pyenv/versions/3.11.8/lib/python3.11/contextlib.py", line 81, in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
    return view_func(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 105, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 515, in dispatch
    response = self.handle_exception(exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 475, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
    raise exc
  File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 512, in dispatch
    response = handler(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/edx-platform/cms/djangoapps/contentstore/rest_api/v1/views/vertical_block.py", line 141, in get
    context = get_container_handler_context(request, usage_key, course, xblock)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/edx-platform/cms/djangoapps/contentstore/utils.py", line 2010, in get_container_handler_context
    component_templates = get_component_templates(course)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/edx-platform/cms/djangoapps/contentstore/views/component.py", line 323, in get_component_templates
    component_class = _load_mixed_class(category)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/edx-platform/cms/djangoapps/contentstore/views/component.py", line 135, in _load_mixed_class
    component_class = XBlock.load_class(category)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/xblock/plugin.py", line 115, in load_class
    PLUGIN_CACHE[key] = cls._load_class_entry_point(selected_entry_point)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/xblock/plugin.py", line 70, in _load_class_entry_point
    class_ = entry_point.load()
             ^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/pkg_resources/__init__.py", line 2495, in load
    self.require(*args, **kwargs)
  File "/openedx/venv/lib/python3.11/site-packages/pkg_resources/__init__.py", line 2518, in require
    items = working_set.resolve(reqs, env, installer, extras=self.extras)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/pkg_resources/__init__.py", line 818, in resolve
    new_requirements = dist.requires(req.extras)[::-1]
                       ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/openedx/venv/lib/python3.11/site-packages/pkg_resources/__init__.py", line 2807, in requires
    raise UnknownExtra(
pkg_resources.UnknownExtra: lxml 5.3.2 has no such extra feature 'html_clean'

It seems that html_clean is no longer available in Ulmo:

lxml[html-clean,html_clean]==5.3.2
lxml[html-clean]==5.3.2

If I install Ulmo from scratch the same errors occur, while they don’t if I install the latest Teak release.

Did anyone experience similar issues or does anyone have an idea what is going wrong here?

Thank you very much in advance for your answers and support!

@christianhueserhzdr can you provide more info about what exactly you’re doing when this error occurs, I did a pip install -r requirements/edx/base.txt on the release/ulmo branch and did not run into any issues.

Are you using tutor or running this on a baremetal system? If it’s not tutor, can you provide more info about your OS, and Python versions?

Dear Feanil @feanil, thank you very much for your reply and questions. I am using Tutor.

Actually, meanwhile I noticed that the reason for the issues with the course units is the markdown-xblock library ( GitHub - cleura/markdown-xblock: An XBlock enabling Open edX course authors to maintain content in Markdown. ) that is not yet ready for Ulmo, but I tried to build a custom openedx image with it. If I leave the library aside in the build, the error disappears.

I’ll wait for the respective pull request for the Ulmo support which will surely fix the issue:

Thanks again for your support!