The binary wants a library the loader can't find: missing package, wrong arch, or a non-standard install dir that needs ldconfig. ldd turns guesswork into a named list.
ldd <binary> 2>&1 | grep 'not found' names the exact unmet dependency. Then find the package that owns it: apt-file find / dnf provides / pacman -F.
Manually installed libs (e.g. /opt/... or /usr/local/lib) aren't in /etc/ld.so.cache. Add the dir to /etc/ld.so.conf.d/ and run ldconfig — LD_LIBRARY_PATH is the quick-and-dirty alternative.
Alpine-built containers running Debian binaries (or vice versa) fail exactly this way: the 'missing' file exists but is the wrong ELF class. file /usr/lib/<...> shows the arch.
ldd <binary> 2>&1 | grep -i 'not found'
apt install libssl-dev 2>/dev/null || apt-file find libssl.so.3 ; # rhel: dnf provides '*/libssl.so.3'
echo /opt/myapp/lib | sudo tee /etc/ld.so.conf.d/myapp.conf && sudo ldconfig
dpkg --print-architecture ; file <binary> # ELF x86-64 binary on aarch64 host = rebuild with the right -march/platform image
LD_LIBRARY_PATH works but is order-sensitive and fragile across shells/contexts — ld.so.conf.d is the durable fix. Static builds (or vendoring libs in the image) kill this entire class of error for shipped tooling.
The library exists somewhere the loader doesn't look by default. Register the directory permanently with /etc/ld.so.conf.d/*.conf + ldconfig instead of exporting paths in every shell.
The loader resolves dependencies before main() runs: the binary exists, its library doesn't. ldd lists all of them — the 'not found' lines are your worklist.
Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.
Browse the template store →One-time. Yours to modify. Instant download from the NinjaOps template store.