HOWTO · Python
How to Fix OSError: [Errno 8] Exec Format Error in Python
Diagnose OSError: [Errno 8] Exec format error when Python launches a shell script on Linux. Reproduce the failure and fix it with a shebang or an explicit interpreter.
On this page
On Linux, Python can raise OSError: [Errno 8] Exec format error when it asks the operating system to run a file directly, but the file does not have a recognized executable format. A common case is a shell script with no interpreter directive (shebang). This is an operating-system launch error, not a Python syntax error. The examples below use the subprocess module and show two fixes: add #!/bin/sh as the script’s first line, or invoke sh explicitly.
Why OSError: [Errno 8] Exec format error occurs
With a direct call such as subprocess.run([script_path]), Linux examines the target file to determine how to execute it. A script needs a valid shebang naming an available interpreter; a compiled program needs a format and architecture the system can execute. If Linux cannot identify a handler for the file, it reports OSError: [Errno 8] Exec format error to Python.
This differs from a permission failure. The reproduction below needs the script to have execute permission so the operating system reaches format handling. Without that permission, direct execution can fail earlier with a permission error instead. Adding execute permission alone does not supply a missing shebang or repair an unsupported executable format.
Reproduce the error with a shell script
The following Linux example creates an executable shell script without a shebang, then attempts to launch it directly. It captures the launch failure so the example itself can finish normally; inspect failure while debugging your own call.
import subprocess
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as directory:
script = Path(directory) / "hello.sh"
script.write_text("printf 'Hello from the script\\n'\n", encoding="utf-8")
script.chmod(0o755)
failure = None
try:
subprocess.run([str(script)], check=True, capture_output=True, text=True)
except (OSError, subprocess.CalledProcessError) as error:
failure = error
The temporary file is executable, and its contents are valid shell syntax, but it has no first-line interpreter directive. The exact errno and message depend on the operating system; this diagnosis applies to the Linux case described above.
Add a shebang to the script
Put #!/bin/sh at the very beginning of the file, before any commands. The operating system reads this interpreter directive during direct execution. Keep it on the first line, save the file as plain text, and make sure /bin/sh is available. The example creates a fresh script with the directive and runs it directly.
Run this example:
import subprocess
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as directory:
script = Path(directory) / "hello.sh"
script.write_text("#!/bin/sh\nprintf 'Hello from the script\\n'\n", encoding="utf-8")
script.chmod(0o755)
result = subprocess.run([str(script)], check=True, capture_output=True, text=True)
print(result.stdout, end="")
Hello from the script
This keeps direct execution and makes the interpreter explicit in the script itself. If the script uses features beyond POSIX shell, choose a shebang for the shell that supports those features and is installed at that path.
Run the script through an interpreter
Alternatively, name the interpreter as the executable and pass the script path as an argument. This does not rely on the script’s shebang, because Linux starts sh directly and sh reads the file. The approach is useful when you cannot change the script or prefer to choose the interpreter at the call site. It still requires the named interpreter and script path to exist.
The self-contained example below uses the same shell command and temporary file pattern.
import subprocess
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as directory:
script = Path(directory) / "hello.sh"
script.write_text("printf 'Hello from the script\\n'\n", encoding="utf-8")
result = subprocess.run(["sh", str(script)], check=True, capture_output=True, text=True)
print(result.stdout, end="")
Hello from the script
Passing a list of arguments lets subprocess invoke sh with the script path as one argument. Avoid building a shell command string from untrusted input; argument lists keep the executable and its arguments separate.
Check the script and executable format
Use these focused checks to locate the launch problem:
- Confirm that the path passed to
subprocessnames the intended file. A missing path generally produces a file-not-found error rather than an execution-format error. - Inspect the first line. For a shell script intended for
/bin/sh, it should be exactly#!/bin/sh; the directive must precede other content. A byte-order mark or other bytes before it can prevent the operating system from recognizing it as the first-line shebang. - Confirm that the interpreter named by the shebang exists and can run on the current system. The explicit-interpreter fix should likewise name an installed interpreter.
- If the target is a compiled executable, check that it was built for the current operating system and processor architecture. Rebuild it for the target environment or use a compatible executable when its format is unsupported.
- Treat execute permission as a separate prerequisite for direct execution. If permission is missing, resolve that permission issue separately; changing permissions does not fix an unrecognized file format.
These checks distinguish an invalid or unrecognized executable format from a wrong path or a permission problem, while keeping the remedy tied to the way the script is launched.