Skip to content

“lxml & xmlsec libxml2 library version mismatch” error under uWSGI #320

Description

@andersk

If libxml2-dev was installed when uWSGI was built, then importing xmlsec within uWSGI leads to an incorrect error xmlsec.InternalError: (-1, 'lxml & xmlsec libxml2 library version mismatch'). There’s no such error outside of uWSGI.

(I can work around this error with --no-binary=lxml --no-binary=xmlsec, but that wastes a lot more CI time and shouldn’t be necessary.)

Reproduction in a fresh container:

$ docker run --rm -it ubuntu:22.04
root@076333186bac:/# apt update
…
root@076333186bac:/# apt install -y gcc libxml2-dev python3-dev python3-venv pkg-config
…
root@076333186bac:/# python3 -m venv venv
root@076333186bac:/# . venv/bin/activate
(venv) root@076333186bac:/# pip install uWSGI xmlsec
…
Successfully installed lxml-5.2.1 uWSGI-2.0.25.1 xmlsec-1.3.14
(venv) root@076333186bac:/# cat > app.py <<EOF
import xmlsec

def application(env, start_response):
    start_response("200 OK", [("Content-Type", "text/plain")])
    return [b"Hello, world!\n"]

EOF
(venv) root@076333186bac:/# python -c 'import xmlsec'
(venv) root@076333186bac:/# uwsgi --http :9090 --wsgi-file app.py
*** Starting uWSGI 2.0.25.1 (64bit) on [Mon May  6 22:18:16 2024] ***
compiled with version: 11.4.0 on 06 May 2024 22:17:53
os: Linux-6.8.7 #1-NixOS SMP PREEMPT_DYNAMIC Wed Apr 17 09:23:43 UTC 2024
nodename: 076333186bac
machine: x86_64
clock source: unix
detected number of CPU cores: 12
current working directory: /
detected binary path: /venv/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
*** WARNING: you are running uWSGI without its master process manager ***
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :9090 fd 4
spawned uWSGI http 1 (pid: 4203)
uwsgi socket 0 bound to TCP address 127.0.0.1:46691 (port auto-assigned) fd 3
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
Python version: 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x55a23eea0bc0
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72904 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
Traceback (most recent call last):
  File "app.py", line 1, in <module>
    import xmlsec
xmlsec.InternalError: (-1, 'lxml & xmlsec libxml2 library version mismatch')
unable to load app 0 (mountpoint='') (callable not found or import error)
*** no app loaded. going in full dynamic mode ***
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 4202, cores: 1)

Activity

  1. andersk commented on May 7, 2024

    @andersk
    Author

    Some debugging information:

    >>> import ctypes, lxml, xmlsec
    >>> libxml2 = ctypes.CDLL("libxml2.so.2")
    >>> ctypes.c_char_p.in_dll(libxml2, "xmlParserVersion").value
    b'20913'
    >>> lxml.etree.LIBXML_VERSION
    (2, 12, 6)
    >>> lxml.etree.LIBXML_COMPILED_VERSION
    (2, 12, 6)
    >>> xmlsec.get_libxml_version()
    (2, 12, 6)
    >>> xmlsec.get_libxml_compiled_version()
    (2, 12, 6)

    xmlParserVersion, LIBXML_VERSION, and LIBXML_COMPILED_VERSION are the same inside and outside uWSGI.

  2. eliasmazur commented on May 20, 2024

    @eliasmazur

    I'm getting this same error on a container that I just re-compiled and it was working fine. I use python3-saml and that's breaking with this error when I run the container.

    Here is the log:

    [2024-05-20 02:54:20 +0000] [11] [ERROR] Exception in worker process
    2024-05-19 22:54:20 Traceback (most recent call last):
    2024-05-19 22:54:20   File "/usr/local/lib/python3.6/dist-packages/gunicorn/arbiter.py", line 583, in spawn_worker
    2024-05-19 22:54:20     worker.init_process()
    2024-05-19 22:54:20   File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/ggevent.py", line 203, in init_process
    2024-05-19 22:54:20     super(GeventWorker, self).init_process()
    2024-05-19 22:54:20   File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/base.py", line 129, in init_process
    2024-05-19 22:54:20     self.load_wsgi()
    2024-05-19 22:54:20   File "/usr/local/lib/python3.6/dist-packages/gunicorn/workers/base.py", line 138, in load_wsgi
    2024-05-19 22:54:20     self.wsgi = self.app.wsgi()
    2024-05-19 22:54:20   File "/usr/local/lib/python3.6/dist-packages/gunicorn/app/base.py", line 67, in wsgi
    2024-05-19 22:54:20     self.callable = self.load()
    2024-05-19 22:54:20   File "/usr/local/lib/python3.6/dist-packages/gunicorn/app/wsgiapp.py", line 52, in load
    2024-05-19 22:54:20     return self.load_wsgiapp()
    2024-05-19 22:54:20   File "/usr/local/lib/python3.6/dist-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
    2024-05-19 22:54:20     return util.import_app(self.app_uri)
    2024-05-19 22:54:20   File "/usr/local/lib/python3.6/dist-packages/gunicorn/util.py", line 350, in import_app
    2024-05-19 22:54:20     __import__(module)
    2024-05-19 22:54:20   File "/opt/app/tinyflask/__init__.py", line 11, in <module>
    2024-05-19 22:54:20     import tinyflask.views
    2024-05-19 22:54:20   File "/opt/app/tinyflask/views.py", line 24, in <module>
    2024-05-19 22:54:20     from onelogin.saml2.auth import OneLogin_Saml2_Auth
    2024-05-19 22:54:20   File "/usr/local/lib/python3.6/dist-packages/onelogin/saml2/auth.py", line 12, in <module>
    2024-05-19 22:54:20     import xmlsec
    2024-05-19 22:54:20 xmlsec.InternalError: (-1, 'lxml & xmlsec libxml2 library version mismatch')
    2024-05-19 22:54:20 [2024-05-20 02:54:20 +0000] [11] [INFO] Worker exiting (pid: 11)
    

    Here is my Dockerfile:

    FROM ubuntu:bionic
    
    RUN apt update
    RUN apt-get update
    RUN apt-get -y upgrade
    RUN apt-get install -y pkg-config
    RUN apt-get install -y software-properties-common apt-utils
    RUN add-apt-repository -y ppa:deadsnakes/ppa
    RUN apt-get install -y vim
    RUN apt-get install -y python3.7
    RUN apt-get install -y python3-pip
    
    RUN apt-get install -y libxml2-dev libxmlsec1-dev
    
    RUN mkdir -p /opt/app
    WORKDIR /opt/app/
    COPY . .
    RUN pip3 install --upgrade pip
    RUN pip3 install --no-cache-dir -r requirements.txt
    
    RUN pip3 install python3-saml
    
    RUN touch /var/log/cron.log
    
    RUN echo "35 6 * * * root /usr/bin/python3 /opt/app/last_login.py >> /opt/app/audit.log" >> /etc/crontab
    
    CMD (cron) && exec gunicorn tinyflask:app -b 0.0.0.0:80 --workers 3 -k gevent
    
    

    And this is the requirements.txt:

    Click==7.0
    Flask==1.1.1
    Flask-Cors==3.0.8
    gevent==1.4.0
    greenlet==0.4.15
    gunicorn==19.9.0
    itsdangerous==1.1.0
    Jinja2==2.10.1
    MarkupSafe==1.1.1
    Werkzeug==0.15.5
    flask-compress==1.4.0
    requests==2.24.0
    python-dateutil==2.8.0
    pytz==2021.1
    pickleshare==0.7.5
    xmltodict
    
    

    I'm stuck. Any help is appreciated.

    Thanks

  3. andres-holvi commented on May 20, 2024

    @andres-holvi

    It seems like lxml@5.2.1 uses libxml2@2.12.6. However, libxml2@2.12.7 has been released, and python-xmlsec@1.3.14 breaks because of this libxml2 version mismatch (?)

    Not sure who should be in charge of fixing this, but I suppose using libxml2@2.12.6 could work.

  4. gregbrant2 commented on May 20, 2024

    @gregbrant2

    @eliasmazur I have the same use case as you with python3-saml. Based on what @andersk said, I've restricted the package version of LXML like so

    lxml >= 4.6.5, !=4.7.0, <=5.2.1 
    

    My build is working again now.

  5. eliasmazur commented on May 20, 2024

    @eliasmazur

    Thanks for the help. I realized I was restricting all packages except xmlsec. I restricted to an earlier version and it now works. Looks like python3-saml was installing the latest xmlsec and that was causing the mismatch.

  6. mstuttgart commented on May 24, 2024

    @mstuttgart

    In my work, we use sigxml and xmlsec. Both install lxml with binaries, causing the same error.

    xmlsec.InternalError: (-1, 'lxml & xmlsec libxml2 library version mismatch')

    To resolve this, I install using the --no-binary pip flag. (work on Ubuntu 22.04, Python 3.10 and Pip 22.0.2)

    pip install --no-binary lxml==4.6.3 lxml==4.6.3 --force-reinstall
    pip install --no-binary xmlsec==1.3.13 xmlsec==1.3.13
    pip install --no-binary signxml==3.2.2 signxml==3.2.2
    
  7. buddhi-vamsi13 commented on May 31, 2024

    @buddhi-vamsi13

    Thanks for the help. I realized I was restricting all packages except xmlsec. I restricted to an earlier version and it now works. Looks like python3-saml was installing the latest xmlsec and that was causing the mismatch.

    Hi,

    we have the similiar issue can you provide us the version which u have mentioned

  8. eliasmazur commented on May 31, 2024

    @eliasmazur

    For the libxml in Dockerfile:
    RUN apt-get install -y libxml2-dev=2.9.4+dfsg1-6.1ubuntu1.9 libxmlsec1-dev=1.2.25-1build1

    For the lxml and xmlsec in requirements.txt:
    lxml==4.9.3
    xmlsec==1.3.13

    Hope this helps.

  9. sergei-maertens commented on Jun 19, 2024

    @sergei-maertens

    Would this mean that a new release/wheel is needed also built with libxml2@2.12.7? I was very excited about being able to install binary wheels again with xmlsec 1.3.14, but it seems that a patch release of libxml broke that again?

  10. sergei-maertens commented on Jun 19, 2024

    @sergei-maertens

    @eliasmazur I have the same use case as you with python3-saml. Based on what @andersk said, I've restricted the package version of LXML like so

    lxml >= 4.6.5, !=4.7.0, <=5.2.1 
    

    My build is working again now.

    Trying this, the problem is not solved for us:

    defusedxml==0.7.1
    et-xmlfile==1.1.0
    lxml==5.2.1
    lxml_html_clean==0.1.1
    xmlsec==1.3.14
    xmltodict==0.12.0
    

    still produces the uwsgi startup crash, while a normal python interpreter is fine (just as reported in the initial description). I have tried uwsgi 2.0.23 and 2.0.26 so far.

    Making sure that libxml2-dev is NOT present in the system packages when uwsgi is being installed/built resolves the issue.

  11. 15 remaining items

  12. ShaheedHaque commented on Jun 16, 2025

    @ShaheedHaque

    FWIW, Ubuntu 25.04 comes with:

    libxml2-dev:amd64   2.12.7+dfsg+really2.9.14-0.4ubuntu0.1
    libxmlsec1-dev      1.2.41-1build1
    python3-lxml:amd64  5.3.2-1
    

    Unsurprisingly, I found I was able to get away with just setting my venv with one pin on lxml<5.4. The venv has python3-saml at 1.16.0.

  13. ttrei commented on Jul 4, 2025

    @ttrei

    Encountered the "lxml & xmlsec libxml2 library version mismatch" error with following version combination (both installed using linux binary wheels from pypi.org):

    lxml==5.4.0
    xmlsec==1.3.14
    

    Downgrading lxml resolved the issue:

    lxml==5.3.2
    xmlsec==1.3.14
    
  14. josephsw commented on Jul 21, 2025

    @josephsw

    FYI: Looks like this was fixed in xmlsec 1.3.16 (when used with lxml 6.0.0).
    https://github.com/xmlsec/python-xmlsec/releases/tag/1.3.16

    Edit: not fixed for uWSGI, see below

  15. andersk commented on Jul 21, 2025

    @andersk
    Author

    This is not fixed. The reproduction recipe from my original report still gives the same error with the current versions (uWSGI 2.0.30, xmlsec 1.3.16, lxml 6.0.0).

  16. josephsw commented on Jul 22, 2025

    @josephsw

    Following your repro steps, it looks like it installs libxml2-dev arm64 2.9.13+dfsg-1ubuntu0.7 at the apt install -y gcc libxml2-dev python3-dev python3-venv step (and I can repro the error when running uwsgi following those steps).

    I'm guessing the issue stems from uWSGI also using libxml2, but it depending on your system version instead of some compiled wheel version.

    I tried manually compiling the libxml2 2.14.4 source (mentioned in the python-xmlsec 1.3.16 release notes), recompiling the lxml and xmlsec python dependencies against that (pip install --no-binary :all: --force-reinstall lxml xmlsec after installing meson and a bunch of dependencies) and then running the uwsgi server again, and the error no longer appears (curl -v http://127.0.0.1:9090/ returned Hello, world!). So depending on what your setup looks like, recompiling against source may be an option (it's also noted in the python-xmlsec 1.3.16 release notes):

    Build both lxml and python-xmlsec manually from source using the same libxml2 version

  17. andersk commented on Jul 22, 2025

    @andersk
    Author

    My original report explained why I don’t want to do that. It’s expensive.

    (I can work around this error with --no-binary=lxml --no-binary=xmlsec, but that wastes a lot more CI time and shouldn’t be necessary.)

  18. phette23 commented on Jul 22, 2025

    @phette23

    I think @ josephsw is right. We are working around this by installing uWSGI with UWSGI_PROFILE_OVERRIDE="xml=no" with compatible versions of python-xmlsec and lxml. uWSGI seems to use a different libxml2 and coerces xmlsec to use it too, while lxml sticks with its builtin. Or that's my theory.

  19. mxamin commented on Jul 23, 2025

    @mxamin
    Collaborator

    uWSGI preloads libxml2.so into the global symbol table, which interferes with Python modules like xmlsec that are statically linked to their own libxml2 copy. This happens because the dynamic linker prefers already-loaded symbols, causing xmlsec to bind to the wrong libxml2 at runtime. The issue aligns with standard ELF/RTLD_GLOBAL behavior. It’s difficult to fully isolate without dynamic linking or symbol exporting control, so for now, I’m planning to properly address it in #356

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions