ImportError: DLL load failed while importing _ssl" after upgrading a native python package on windows CI
Fixes ImportError: DLL load failed while importing _ssl on Windows CI after a native Python package upgrade. Use it when Python starts but importing ssl (or anything using TLS, like pip and requests) fails on a Windows runner. Key trigger: the interpreter's OpenSSL DLLs (libssl and libcrypto) are missing from the DLL search path, almost always because a conda install and a pip install were mixed or the Python install was replaced without its DLLs.
TL;DR: Python's ssl module is a thin wrapper over OpenSSL DLLs, and on Windows those DLLs must sit next to the interpreter or on the DLL search path. Confirm you are running one consistent Python (no conda plus pip mixing), verify the DLLs exist beside python.exe, and reinstall Python cleanly if they are gone. In CI, pin the interpreter setup step and never mix package managers in one job.
The error
"ImportError: DLL load failed while importing _ssl" after upgrading a native python package on windows CISteps to fix
Confirm which interpreter runs: where python and python -c "import sys; print(sys.executable)" should agree. Expected: One path prints for both, proving there is a single interpreter in play.
Reproduce narrowly: python -c "import ssl; print(ssl.OPENSSL_VERSION)". Expected: Either a version string prints (ssl is fine and the failure is elsewhere) or the DLL load error repeats.
Check the DLLs: look next to python.exe for libssl and libcrypto DLLs, and check that no stray copies from another install shadow them on PATH. Expected: You find the DLLs missing, mismatched, or duplicated from a second Python install.
Fix by reinstalling one clean Python: use the official installer or a fresh conda environment, then reinstall packages with that interpreter's pip only. Expected: import ssl prints the OpenSSL version and pip can reach the index over TLS.
In CI, pin the setup step (for example one setup-python version for the whole job) and remove any step that installs a second Python or mixes conda and pip. Expected: The workflow goes green and stays green across runs.
Use this when
- Python on Windows CI fails with DLL load failed while importing _ssl after a package upgrade
- pip itself fails on Windows with an ssl error right after the interpreter was changed
- A native package upgrade on a Windows runner broke every TLS-dependent import
Not for this skill when
- Linux or macOS ssl import errors, which are shared-library path problems, not DLL problems
- Certificate verification failures (CERTIFICATEVERIFYFAILED), which mean ssl loaded fine but trust is misconfigured
- Pure-Python ImportErrors with no DLL mention
Variant phrasings
- ImportError DLL load failed while importing _hashlib
- python ssl module not available on windows
- pip fails with SSLError after python upgrade on windows CI
Why it happens
CPython's _ssl extension links dynamically against OpenSSL. On Windows there is no system OpenSSL to fall back on, so the installer ships libssl and libcrypto DLLs next to python.exe. Upgrading a native package (or swapping interpreters mid-image) can delete, replace, or shadow those DLLs with incompatible ones, and then every import of ssl fails at load time. Mixing conda Python with pip-installed wheels is the classic trigger because the two ecosystems ship different OpenSSL builds.
Edge cases
- A second Python on PATH can shadow the DLLs even when your target install is healthy; where python showing two entries is the giveaway.
- Some runners cache the Python install directory between jobs; a poisoned cache reintroduces the broken DLLs until the cache key changes.
- On Python 3.8 and newer, os.adddlldirectory can extend the search path at runtime, but fixing the install is more durable than a code workaround.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_dOTtFUmoOxX5ICj9GDmKfg