From 2fef1dad1fc83f98aeaeb4f19a57f0bf097ee896 Mon Sep 17 00:00:00 2001 From: Bertrand Bonnefoy-Claudet Date: Sat, 10 Jan 2026 19:06:42 +0100 Subject: [PATCH] Fix handling of missing command by `dotenv run` Changes for users: - (BREAKING) `dotenv run` exits with status code 1 instead of 2 if the command provided as argument can't be found. - `dotenv run` prints a friendly error message instead of a stack trace if the command provided as argument can't be found. Notes: The existing test case was wrongly testing for that situation: it was actually observing a "missing env file" error, not a "command not found error". I thus added an appropriate test case for full coverage. --- src/dotenv/cli.py | 15 +++++++++++++-- tests/test_cli.py | 13 ++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/dotenv/cli.py b/src/dotenv/cli.py index c548aa39..677bda2f 100644 --- a/src/dotenv/cli.py +++ b/src/dotenv/cli.py @@ -210,9 +210,20 @@ def run_command(command: List[str], env: Dict[str, str]) -> None: if sys.platform == "win32": # execvpe on Windows returns control immediately # rather than once the command has finished. - p = Popen(command, universal_newlines=True, bufsize=0, shell=False, env=cmd_env) + try: + p = Popen( + command, universal_newlines=True, bufsize=0, shell=False, env=cmd_env + ) + except FileNotFoundError: + print(f"Command not found: {command[0]}", file=sys.stderr) + sys.exit(1) + _, _ = p.communicate() sys.exit(p.returncode) else: - os.execvpe(command[0], args=command, env=cmd_env) + try: + os.execvpe(command[0], args=command, env=cmd_env) + except FileNotFoundError: + print(f"Command not found: {command[0]}", file=sys.stderr) + sys.exit(1) diff --git a/tests/test_cli.py b/tests/test_cli.py index 343fdb23..f5de94c4 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -237,7 +237,18 @@ def test_run_without_cmd(cli): assert "Invalid value for '-f'" in result.output -def test_run_with_invalid_cmd(cli): +def test_run_with_invalid_cmd(cli, dotenv_path): + result = cli.invoke(dotenv_cli, ["--file", dotenv_path, "run", "i_do_not_exist"]) + + assert result.exit_code == 1 + assert "Command not found: i_do_not_exist" in result.output + + +def test_run_with_env_missing_and_invalid_cmd(cli): + """ + Check that an .env file missing takes precedence over a command not found error. + """ + result = cli.invoke(dotenv_cli, ["run", "i_do_not_exist"]) assert result.exit_code == 2