"error while loading shared libraries" and "GLIBC_2.xx not found": what the loader is telling you
Fix Linux "error while loading shared libraries: cannot open shared object file" and "version GLIBC_2.xx not found": use ldd, install the library, run ldconfig, rebuild.
by OhSudo ··
Checked on real software: Debian, Ubuntu, Rocky Linux · November 2026How we check
Two errors from the same part of Linux. The first:
./app: error while loading shared libraries: libssl.so.3: cannot open shared object file: No such file or directoryThe second:
./app: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by ./app)Most programs don’t contain all their code, and at start the dynamic loader brings in the libraries they need. The first message means it can’t find a library. The second means it found one, and that one’s too old for this program.
They need different fixes. The first is usually a package to install. The second means the program was built on a newer system than yours, and installing packages won’t solve it.
- The programneeds libssl.so.3, GLIBC_2.38starts
- Dynamic loadersearches the library pathsfinds(fails)
- Missing, or too oldcannot open shared object / version not found(breaks here)
TL;DR
ldd ./app | grep 'not found' # what's missing?apt-file search libssl.so.3 # Debian / Ubuntu: which package?dnf provides '*/libssl.so.3' # RHELsudo ldconfig # after installing a library by handFor GLIBC_2.xx: run it on a system that new, in a container, or build it on the oldest system you support.
1. See everything that’s missing
ldd ./applinux-vdso.so.1 (0x00007ffd...)libssl.so.3 => not foundlibcrypto.so.3 => not foundlibc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f...)The loader stops at the first one it misses, and ldd shows them all. Don’t use ldd on a program you don’t trust, because it can run its code. objdump -p ./app | grep NEEDED is safe.
2. Install the package
Find which package has that file:
# Debian / Ubuntusudo apt install apt-file && sudo apt-file updateapt-file search libssl.so.3
# RHEL / Rocky / AlmaLinuxdnf provides '*/libssl.so.3'Then install it. Some usual ones:
| Library | Debian / Ubuntu | RHEL |
|---|---|---|
libssl.so.3 |
libssl3t64 or libssl3 |
openssl-libs |
libstdc++.so.6 |
libstdc++6 |
libstdc++ |
libz.so.1 |
zlib1g |
zlib |
libpq.so.5 |
libpq5 |
libpq |
libmysqlclient.so.21 |
libmysqlclient21 |
mysql-libs |
Names vary by release, which is why you should search. A library with -dev or -devel is for compiling: you don’t need it just to run a program.
3. An old version number
The number at the end is the point here. libssl.so.1.1 isn’t libssl.so.3, and they’re not compatible. A program built for OpenSSL 1.1 needs exactly that, and your new system ships only 3:
libssl.so.1.1: cannot open shared object fileThe clean ways out are to get a build for your release, or run the old program in a container with the older system.
Don’t make a link from the new name to the old one, as forums often suggest:
sudo ln -s libssl.so.3 libssl.so.1.1 # don'tThe two versions aren’t compatible, and the program may start, then crash, or misbehave without an error, in code that handles your encryption.
4. It’s installed, and still not found
The loader looks in a cache of known folders, not across the whole disk. A library in /usr/local/lib, or in an application’s own folder, may not be in it:
ldconfig -p | grep libfoosudo find / -name 'libfoo.so*' 2>/dev/nullAdd the folder, and rebuild the cache:
echo '/opt/foo/lib' | sudo tee /etc/ld.so.conf.d/foo.confsudo ldconfigAfter installing from source to /usr/local/lib, a plain sudo ldconfig is often all that’s missing.
For one program only, without changing the system, use an environment variable:
LD_LIBRARY_PATH=/opt/foo/lib ./appIt works, but it’s fragile: sudo and cron drop it. For services, set Environment=LD_LIBRARY_PATH=... in the unit, or a proper .conf file as above.
Also check the architecture. A 32-bit program needs 32-bit libraries, even if the 64-bit ones are there. file ./app tells you which it is, and on Debian, that needs libc6:i386 and the like.
5. GLIBC_2.xx not found
./app: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.38' not found (required by ./app)The program was compiled on a newer system, and uses features your glibc doesn’t have. See what you have, and what it wants:
ldd --version | head -n 1objdump -T ./app | grep -o 'GLIBC_[0-9.]*' | sort -Vu | tail -n 3Here are the typical glibc versions, so you can see which system would do:
| System | glibc |
|---|---|
| Debian 11 | 2.31 |
| Ubuntu 22.04 | 2.35 |
| Debian 12 | 2.36 |
| RHEL 9 | 2.34 |
| Ubuntu 24.04 | 2.39 |
| Debian 13 | 2.41 |
So what do you do?
- Get a build made for your system. Vendors often offer one, or a static or
muslbuild. - Build it yourself on your system, or on the oldest one you support. A binary built on an old glibc runs on newer ones, and not the other way round.
- Run it in a container with a newer base image.
- Upgrade the machine to a newer release.
In CI, this comes up when building on ubuntu-latest and deploying to an older server. Build in a container of your oldest target, or link statically: with Go, CGO_ENABLED=0.
Never replace your system’s glibc by hand, or install a newer one over it. Nearly every program depends on it, including ls, bash and sudo, so a mismatch can leave you with a machine that can’t run any command, and doesn’t boot.
6. In Docker
This shows up when you copy a binary between images. For example, built on debian:13 and run on debian:11, or the same thing with libraries missing on a -slim image:
FROM debian:13-slim AS build# ...
FROM debian:13-slim # the same release as the buildRUN apt-get update && apt-get install -y --no-install-recommends libpq5COPY --from=build /app /appTo see what’s missing in the final image, run docker run --rm -it myimage ldd /app. For Go, the Dockerfile Generator builds with cgo turned off, so the binary needs no libraries at all. Alpine is a different problem, as it has no glibc at all: see not found for a binary that’s there.
Warning
Don’t download a .so from a website to get past this. A library runs inside your program, with all its rights. Use your distribution’s packages, or the vendor’s.
Shell, we have a problem!
Similar, but different: command not found means the program itself isn’t on your PATH. no such file or directory for a file that’s right there often means its loader is missing: see the Alpine article. exec format error means another CPU architecture: see that article. And Python’s ImportError: libfoo.so is this same problem, in a Python package.
Found this useful? Share it.
Found a mistake? Let us know at contact@ohsudo.com.