Python subprocess FileNotFoundError on a binary that is clearly installed: PATH, cwd, and the shell you did not use
Problem
ffmpeg works in the shell. The Python job cannot find it:
Traceback (most recent call last):
File "/srv/app/jobs/render.py", line 18, in <module>
subprocess.run(["ffmpeg", "-i", clip, out])
File "/usr/local/lib/python3.12/subprocess.py", line 554, in run
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), cmd[0])
FileNotFoundError: [Errno 2] No such file or directory: 'ffmpeg'The scheduler ran the job from cron; the developer tested it from an interactive shell. Same script, different environment — and the difference is entirely in PATH.
Root cause
subprocess execs using the current process's environment, which is not your shell's:
1. cron/systemd/CI give a minimal PATH (/usr/bin:/bin); interactive shells source .zshrc and pyenv shims. Binaries in /usr/local/bin or ~/.local/bin vanish under schedulers. 2. Relative binary paths + cwd=: subprocess.run(["./tool"], cwd="/srv/app") resolves ./tool relative to the new cwd — if the shell that launched Python was elsewhere, the discovery worked in testing and fails in prod (or vice versa). 3. A venv's PATH: activating a venv prepends its bin; a job that inherits the venv can find venv-installed CLIs, one that does not cannot — neither is "installed".
import shutil, subprocess
FFMPEG = shutil.which("ffmpeg") or "/usr/local/bin/ffmpeg"
… 3 more lines in the fix🔒 the fix — including 3 code blocks — is members-only. $1/mo unlocks everything.