execve() failed because the kernel couldn’t find the executable file.

This is a classic "file not found" scenario, but strace shows it at the syscall level, giving us direct insight into the kernel’s perspective. The execve() syscall is the kernel’s attempt to replace the current process image with a new one specified by the executable path. When it fails, it’s because the kernel, following a specific search path and set of rules, couldn’t locate the file it was asked to run.

Here are the most common reasons execve() fails with ENOENT (No such file or directory) and how to diagnose them:

  1. Typo in the executable path: This is the most frequent culprit. You might have mistyped the command name or provided an incorrect path.

    • Diagnosis: Look at the first argument to execve() in your strace output. This is the path the kernel tried to execute.
      # Example strace output snippet:
      execve("/usr/local/bin/my-app", ["/usr/local/bin/my-app", "-v"], 0x7fffa4026820 /* 28 vars */) = -1 ENOENT (No such file or directory)
      
    • Fix: Double-check the command you’re typing. Use which <command> or command -v <command> to find the correct path if it’s in your PATH. If it’s a direct path, ensure every character is correct.
      # If 'my-app' is actually in /usr/bin/
      which my-app
      # Output: /usr/bin/my-app
      # Then execute:
      /usr/bin/my-app -v
      
    • Why it works: The kernel can only find what’s explicitly given. Correcting the path tells the kernel where the file actually resides.
  2. Executable not in PATH: If you’re trying to run a command without specifying its full path (e.g., my-command instead of /opt/myapp/bin/my-command), the system searches directories listed in your PATH environment variable. If the executable isn’t in any of those directories, execve() will fail.

    • Diagnosis: Examine the PATH environment variable before running the command.
      echo $PATH
      # Example output: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      
      Then, check if your executable’s directory is present.
    • Fix: Add the directory containing your executable to your PATH. This is usually done in your shell’s configuration file (e.g., ~/.bashrc, ~/.zshrc).
      # Add to ~/.bashrc
      export PATH="$PATH:/opt/myapp/bin"
      # Then source the file or open a new terminal
      source ~/.bashrc
      # Now you can run 'my-command' directly
      my-command
      
    • Why it works: By adding the directory to PATH, you’re telling the shell (and subsequently execve()) where to look for executables when a full path isn’t provided.
  3. Missing interpreter (Shebang line): For script files (like shell scripts, Python scripts, etc.), the first line typically specifies the interpreter to use (e.g., #!/bin/bash or #!/usr/bin/env python3). If this interpreter path is incorrect or the interpreter itself is not found, execve() will fail. Note that strace might show execve() for the script and then another execve() for the interpreter, which might be the one failing.

    • Diagnosis: Inspect the first line of the script file.
      head -n 1 /path/to/your/script.sh
      # Example output: #!/usr/bin/env python3
      
      Then, check if that interpreter exists and is executable.
      ls -l /usr/bin/env
      ls -l /usr/bin/python3
      
    • Fix: Correct the shebang line to point to the actual, existing interpreter, or install the missing interpreter. If using #!/usr/bin/env, ensure env is in your PATH.
      # Corrected shebang for Python 3
      #!/usr/bin/python3
      # Or ensure /usr/bin/env is working and in PATH
      
    • Why it works: The kernel needs a valid interpreter to execute script code. Providing a correct path to an existing interpreter allows the script to be processed.
  4. File Permissions: While ENOENT usually means "not found," sometimes very restrictive permissions can mask existence or prevent the lookup entirely in specific scenarios, though EACCES (Permission denied) is more common for outright permission issues. However, if the directory containing the executable has its execute permission (x) removed for the user running the process, the kernel cannot search into that directory to find the file, leading to ENOENT.

    • Diagnosis: Check permissions of the executable and its parent directories.
      ls -ld /path/to/
      ls -l /path/to/executable
      
      Specifically, ensure the user running the process has execute (x) permission on all parent directories leading to the executable.
    • Fix: Grant execute permission on the necessary directories.
      chmod +x /path/to/
      
    • Why it works: The x permission on a directory allows a process to traverse into it and stat files within it. Without it, the directory is effectively opaque, and files within cannot be found.
  5. Filesystem Issues / Mount Points: The executable might reside on a filesystem that is not currently mounted, or the mount point itself might be misconfigured.

    • Diagnosis: Check your mounted filesystems.
      mount | grep '/path/to/mountpoint'
      
      If the filesystem is supposed to be mounted but isn’t, investigate why (e.g., check /etc/fstab, system logs).
    • Fix: Mount the filesystem.
      sudo mount -a # If defined in /etc/fstab
      # or
      sudo mount /dev/sdXn /path/to/mountpoint
      
    • Why it works: The kernel can only access files on mounted filesystems. Mounting makes the filesystem’s contents visible to the operating system.
  6. Chroot or Container Environment: If the process is running within a chroot jail or a container (like Docker), the executable’s path is relative to the root of that jailed/containerized environment. The file might exist on the host system but not within the isolated environment.

    • Diagnosis: Determine the root of the chroot or container. Then, check if the executable exists at the specified path relative to that root.
      # For chroot, you'd typically be inside it, so just check the path
      ls -l /path/to/executable
      # For Docker, inspect the container's filesystem or exec into it
      docker exec -it <container_id> ls -l /path/to/executable
      
    • Fix: Ensure the executable is copied into the chroot directory or container image at the correct path, or adjust the command to use a path that does exist within the environment.
      # Example: Copying executable into a chroot
      sudo cp /host/path/to/my-app /chroot/path/to/my-app
      
    • Why it works: chroot and containers create isolated filesystem views. The execve() call operates strictly within these boundaries, so the file must exist inside the isolated view.

After fixing the ENOENT error, your next likely issue will be EACCES (Permission denied) if the executable itself is not executable, or a different strace output related to the successful execution of your program.

Want structured learning?

Take the full Strace course →