From 0d174d014f94c8418fe1449aae01468b1e3e9ac8 Mon Sep 17 00:00:00 2001 From: Quratulain-bilal Date: Fri, 31 Jul 2026 20:51:13 +0500 Subject: [PATCH] fix: catch OSError in streaming dispatch_command() for missing/unexecutable binaries The streaming branch only caught KeyboardInterrupt but not OSError. If the binary is removed between shutil.which() and subprocess.run() (a TOCTOU race), an OSError propagates unhandled. --- src/specify_cli/integrations/base.py | 6 ++++++ src/specify_cli/integrations/copilot/__init__.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/specify_cli/integrations/base.py b/src/specify_cli/integrations/base.py index cca4f13976..a3ac358701 100644 --- a/src/specify_cli/integrations/base.py +++ b/src/specify_cli/integrations/base.py @@ -401,6 +401,12 @@ def dispatch_command( "stdout": "", "stderr": "Interrupted by user", } + except OSError as exc: + return { + "exit_code": 1, + "stdout": "", + "stderr": f"Failed to execute command: {exc}", + } return { "exit_code": result.returncode, "stdout": "", diff --git a/src/specify_cli/integrations/copilot/__init__.py b/src/specify_cli/integrations/copilot/__init__.py index e6f86e8991..57adff7609 100644 --- a/src/specify_cli/integrations/copilot/__init__.py +++ b/src/specify_cli/integrations/copilot/__init__.py @@ -314,6 +314,12 @@ def dispatch_command( "stdout": "", "stderr": "Interrupted by user", } + except OSError as exc: + return { + "exit_code": 1, + "stdout": "", + "stderr": f"Failed to execute command: {exc}", + } return { "exit_code": result.returncode, "stdout": "",