Python ImportError: a Shared Library on LD_LIBRARY_PATH Not Found in CI
A compiled extension imported, but a library it depends on lives in a non-standard prefix the dynamic loader does not search. The fix is to put that directory on LD_LIBRARY_PATH (or register it with ldconfig), not to reinstall the package.
What this error means
Importing a package fails with ImportError: lib<name>.so.N: cannot open shared object file even though the file exists somewhere on disk under a custom prefix (CUDA, a self-built library, a conda lib dir). Adding the directory to LD_LIBRARY_PATH fixes it.
ImportError: libcudart.so.12: cannot open shared object file: No such file or directory
# the file exists, just not on the loader search path:
$ find / -name 'libcudart.so.12' 2>/dev/null
/usr/local/cuda-12/lib64/libcudart.so.12Common causes
Library in a non-standard prefix
The dependent .so is under a custom location (e.g. /usr/local/cuda/lib64) that is not in the default loader search path or ld.so.conf.
LD_LIBRARY_PATH not propagated to the step
A previous step set LD_LIBRARY_PATH, but each CI step is a fresh shell, so a later step that imports the package no longer has it.
How to fix it
Add the library directory to LD_LIBRARY_PATH
export LD_LIBRARY_PATH="/usr/local/cuda-12/lib64:${LD_LIBRARY_PATH}"
python -c "import the_package"Persist it across CI steps
On GitHub Actions, write it to the job environment so later steps inherit it.
- run: echo "LD_LIBRARY_PATH=/usr/local/cuda-12/lib64:${LD_LIBRARY_PATH}" >> "$GITHUB_ENV"Or register the path with ldconfig
echo "/usr/local/cuda-12/lib64" > /etc/ld.so.conf.d/cuda.conf
ldconfigHow to prevent it
- Register custom library prefixes with ldconfig in the runner image.
- Persist
LD_LIBRARY_PATHvia$GITHUB_ENV, not a single step. - Prefer wheels that bundle their native libraries to avoid loader path issues.