guides / no-such-file-or-directory-binary troubleshootingupdated 2026-10-25 readelf -h ./app

No such file or directory when the file is clearly there

2026-10-25 By luckyray Debian 12 · Ubuntu 24.04 · Alpine 3.20
$ ./app
bash: ./app: No such file or directory

$ ls -l ./app
-rwxr-xr-x 1 deploy deploy 1843200 Oct 25 12:04 ./app

$ file ./app
./app: ELF 64-bit LSB pie executable, x86-64, ..., dynamically linked,
       interpreter /lib64/ld-linux-x86-64.so.2

Every instinct says the file is there. And it is. What is missing is the interpreter named in PT_INTERP — and the kernel, having failed to find it, reports ENOENT against the path you executed rather than against the path it could not open.

Why the message is wrong on purpose

execve(2) has one error code for “the thing I needed was not there”: ENOENT. Once the kernel has handed control to the binary format handler and that handler asks the kernel to also open the interpreter, a failure in that second open still returns ENOENT for the whole execve call. The shell prints that against argv[0] because that is the only path it knows.

So the rule is: No such file or directory about a binary that exists = look at PT_INTERP.

Confirming it in one command

$ readelf -l ./app | grep interpreter
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

$ ls -l /lib64/ld-linux-x86-64.so.2
ls: cannot access '/lib64/ld-linux-x86-64.so.2': No such file or directory

There is the real missing file. On this host, ldd --version will show musl, or the system may be a different architecture rootfs entirely.

Three common cases:

PT_INTERP saysHost isCause
/lib64/ld-linux-x86-64.so.2Alpine (musl)glibc binary in a musl image
/lib/ld-musl-x86_64.so.1Ubuntumusl binary on glibc
/lib/ld-linux-aarch64.so.1x86-64wrong architecture — but then Exec format error usually wins instead

The third row is worth knowing: if the architecture is wrong and the interpreter is wrong, which error you get depends on how far the kernel got. Both messages can appear for the same root cause.

The other causes of this exact message

Not all of them are interpreters. In order of frequency:

1. A shebang pointing at a path that does not exist. The message then names the interpreter explicitly (/usr/bin/env/python3: bad interpreter), so it is usually easier.

2. A script with CRLF line endings. The interpreter becomes bash\r. bash ./script works, ./script does not. See Exec format error for the detail.

3. A bind mount or volume that hides the file. Inside a container, ls may show the host’s path via a mount while the process sees an empty mount. stat from inside the container is the test.

4. A dynamically linked binary whose dynamic loader is present but whose ld.so.cache entry is broken — rarer, and it normally produces a library error instead.

Fixing it properly

SituationCorrect fix
glibc binary in Alpinerebuild against musl, or use gcompat as a stopgap
musl binary on Ubuntubuild against glibc, or ship the musl loader
Wrong architectureget the build for the right platform
You control the build-static with musl removes the interpreter entirely

Do not copy ld-linux-x86-64.so.2 from another distribution into the host. You will get a binary that starts and then resolves glibc symbols against musl’s libc, failing at a random later point with a message that has nothing to do with the original problem.

If dropping the loader into a directory is genuinely the right call — vendor distribution, no rebuild possible — invoke it explicitly so PT_INTERP is bypassed:

./bundle/ld-linux-x86-64.so.2 --library-path ./bundle/lib ./app

That is self-contained and reversible, which copying into /lib64 is not.

Checking without a shell

The ELF Inspector shows the interpreter path and the detected libc family (glibc, musl, or static) in the summary tab. If the interpreter is missing on the target, the Dependency Doctor will show the complete DT_NEEDED list too — useful for confirming that fixing the interpreter will not immediately expose the next problem.

Related: musl vs glibc explains the two families, and static vs dynamic linking covers why static builds have no interpreter to miss.


Every command in this guide was run against the distribution named in the output. If your output differs, the mechanism section explains why — and the ELF Inspector shows the same fields without needing a shell.

Related

guides
  1. cannot execute binary file: Exec format error — causes and fixes Why Linux refuses to run a binary with Exec format error, how to confirm the cause in three commands, and the five fixes that actually apply.
  2. version `GLIBC_2.34' not found — why copying libc never works How glibc symbol versioning works, why a binary built on a newer distribution refuses to start on an older one, and the four legitimate fixes.
  3. wrong ELF class: ELFCLASS32 or ELFCLASS64 — what it means The 32-bit versus 64-bit mismatch that shows up at link time and at dlopen time, why it is not the same as Exec format error, and how to resolve it.