Linux ELF Binary Exists but Returns ENOENT? Check PT_INTERP
Diagnose ENOENT for an executable ELF file with readelf, verify its dynamic loader path, and match the build and runtime environments.
If a Linux ELF binary exists and has execute permission but reports No such file or directory, run readelf -lW ./app and check the program interpreter path. When the loader required by a dynamically linked ELF is absent from the runtime environment, the kernel can return ENOENT even though the executable exists. A local example shows how to diagnose this after moving a binary to a container or another distribution.
A cyan executable module beside an empty slot outlined in amber
Why the kernel can return ENOENT for an existing file
A dynamically linked ELF records the interpreter path in its PT_INTERP program header. The kernel opens the loader at that path during execution. execve(2) can return ENOENT when the executable path is absent, or when the ELF interpreter or script interpreter is absent. If the error persists after checking the path and execute permission, inspect the interpreter the binary requests. Linux execve(2) · ELF format
Inspect the loader path and architecture
- Check
Machineinreadelf -hW ./app. Compare it with the intended target architecture. If it differs from the host, check that the runtime has the appropriate emulation configured.
- Find
INTERPandRequesting program interpreterinreadelf -lW ./app. Check that the absolute path is valid in the actual runtime. For a container, check the final image’s filesystem and follow any symlink to its target.
- If the loader is present and the error names a shared library, inspect the
NEEDEDentries fromreadelf -dW ./appand the loader’s search paths.NEEDEDlists the binary’s direct dependencies, so check any further dependencies required by those libraries separately. GNU readelf documentation · Linux ld.so(8)
Reproduce ENOENT with an existing executable
The example builds two binaries from the same C source. It uses a GNU linker option to give the second binary a loader path that does not exist in the temporary directory. On Linux with Python 3, GCC, the GNU linker, and readelf, save it as elf_loader_demo.py and run python3 elf_loader_demo.py. GNU ld options
The example ran on Linux x86-64 with Python 3.12.14, GCC 14.2.0, and GNU Binutils 2.44 on November 13, 2026. The first binary printed successfully. The second failed with ENOENT even though the file existed and had execute permission.
Match the build and runtime environments
For deployment, choose a runtime that matches the architecture and libc family used to build the binary, and include the required shared libraries. When moving a glibc binary to a musl-based image, rebuild for the target or choose a compatible runtime. Matching the loader filename alone can still leave incompatible libc or shared library ABIs. For programs that support static linking, consider a static build and verify whether it has PT_INTERP and whether it runs as expected. Linux ld.so(8) · ELF format
The example verifies the missing ELF loader case locally. Containers, static builds, and execution on other architectures were outside the test scope.