Skip to content
Latchkey

Python subprocess "FileNotFoundError: No such file or directory" in CI

subprocess could not find the program you asked it to run. The error names the executable, not a data file - either the binary isn’t installed/on PATH, or you passed a whole shell command string with shell=False.

What this error means

A subprocess.run/Popen call raises FileNotFoundError: [Errno 2] No such file or directory: '<cmd>'. The "file" in the message is the command itself, so Python couldn’t locate the executable to launch.

Python traceback
subprocess.run(["pdflatex", "doc.tex"])
# FileNotFoundError: [Errno 2] No such file or directory: 'pdflatex'

# or, passing a shell string without shell=True:
subprocess.run("ls -la /tmp")
# FileNotFoundError: [Errno 2] No such file or directory: 'ls -la /tmp'

Diagnose it: which Python, and which index?

A pip failure in CI is usually about the interpreter or the index rather than the package. Runners have several Pythons installed, and the one on PATH is not necessarily the one your virtualenv or your workflow selected.

Terminal
which -a python python3 pip pip3
python -c "import sys; print(sys.executable, sys.version)"
pip config list
pip debug --verbose 2>/dev/null | grep -i "compatible tags" | head -5

Common causes

Executable not installed or not on PATH

The named command isn’t present in the CI image (or its directory isn’t on PATH), so the OS can’t exec it.

A shell command string with shell=False

Passing "ls -la /tmp" as a single arg without shell=True makes subprocess look for a literal executable named ls -la /tmp, which doesn’t exist.

How to fix it

Install the program (and verify PATH)

Terminal
# example: TeX for pdflatex
apt-get update && apt-get install -y texlive-latex-base
python -c "import shutil; print(shutil.which('pdflatex'))"

Pass a list, not a shell string

With shell=False (the default) pass argv as a list. Only use a string with shell=True.

Python
# correct
subprocess.run(["ls", "-la", "/tmp"])
# or, if you really need shell features
subprocess.run("ls -la /tmp", shell=True)

How to prevent it

  • Install required external programs in the runner image.
  • Pass argv as a list to subprocess unless you explicitly need a shell.
  • Probe with shutil.which and fail early with a clear message.

Frequently asked questions

What causes Python subprocess "FileNotFoundError: no such file or directory" in CI?
There are 2 common causes: executable not installed or not on path and a shell command string with shell=false. The named command isn’t present in the CI image (or its directory isn’t on PATH), so the OS can’t exec it.
How do I fix Python subprocess "FileNotFoundError: no such file or directory" in CI?
There are 2 fixes depending on which cause you have: install the program (and verify path) and pass a list, not a shell string. Work through them in order, since the first is the most common.
What does Python subprocess "FileNotFoundError: no such file or directory" in CI actually mean?
A subprocess.run/Popen call raises FileNotFoundError: [Errno 2] No such file or directory: '<cmd>'.
How do I stop Python subprocess "FileNotFoundError: no such file or directory" in CI happening again?
Install required external programs in the runner image. The prevention section lists 3 changes that keep it from recurring.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.

Related guides

References

This is a setup failure, not a bug in your code. Latchkey detects, repairs, and retries it for you. Start free → 30-day trial · No credit card