From a4bd37d6b4537142579bbb62877c8be7ebf29376 Mon Sep 17 00:00:00 2001 From: Quratulain-bilal Date: Wed, 29 Jul 2026 00:42:15 +0500 Subject: [PATCH 1/2] fix: use missing_ok for temp file cleanup to avoid masking errors --- src/specify_cli/_utils.py | 4 ++-- src/specify_cli/integrations/manifest.py | 3 +-- src/specify_cli/shared_infra.py | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/specify_cli/_utils.py b/src/specify_cli/_utils.py index 85b659d67b..b623de81af 100644 --- a/src/specify_cli/_utils.py +++ b/src/specify_cli/_utils.py @@ -192,8 +192,8 @@ def atomic_write_json(target_file: Path, payload: dict[str, Any]) -> None: os.replace(temp_path, target_file) except Exception: - if temp_path and temp_path.exists(): - temp_path.unlink() + if temp_path: + temp_path.unlink(missing_ok=True) raise try: diff --git a/src/specify_cli/integrations/manifest.py b/src/specify_cli/integrations/manifest.py index ef2a9fc893..bde83f000f 100644 --- a/src/specify_cli/integrations/manifest.py +++ b/src/specify_cli/integrations/manifest.py @@ -451,8 +451,7 @@ def save(self) -> Path: _ensure_safe_manifest_destination(self.project_root, path) os.replace(temp_path, path) finally: - if temp_path.exists(): - temp_path.unlink() + temp_path.unlink(missing_ok=True) return path @classmethod diff --git a/src/specify_cli/shared_infra.py b/src/specify_cli/shared_infra.py index 1c8d727d73..001a31e9e1 100644 --- a/src/specify_cli/shared_infra.py +++ b/src/specify_cli/shared_infra.py @@ -262,8 +262,7 @@ def _write_shared_bytes( _ensure_safe_shared_destination(project_path, dest) os.replace(temp_path, dest) finally: - if temp_path.exists(): - temp_path.unlink() + temp_path.unlink(missing_ok=True) _BASH_FORMAT_COMMAND_RE = re.compile( From c0d362cfe78ea9abded3682919aa4680aa7c3ac5 Mon Sep 17 00:00:00 2001 From: Quratulain-bilal Date: Wed, 29 Jul 2026 18:14:42 +0500 Subject: [PATCH 2/2] fix: catch OSError during temp file cleanup to avoid masking errors Wrap unlink(missing_ok=True) in try/except OSError in finally/except blocks to prevent cleanup failures from masking the original exception. --- src/specify_cli/_utils.py | 5 ++++- src/specify_cli/integrations/manifest.py | 5 ++++- src/specify_cli/shared_infra.py | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/specify_cli/_utils.py b/src/specify_cli/_utils.py index b623de81af..1c767cab5b 100644 --- a/src/specify_cli/_utils.py +++ b/src/specify_cli/_utils.py @@ -193,7 +193,10 @@ def atomic_write_json(target_file: Path, payload: dict[str, Any]) -> None: os.replace(temp_path, target_file) except Exception: if temp_path: - temp_path.unlink(missing_ok=True) + try: + temp_path.unlink(missing_ok=True) + except OSError: + pass raise try: diff --git a/src/specify_cli/integrations/manifest.py b/src/specify_cli/integrations/manifest.py index bde83f000f..ffd6251d0b 100644 --- a/src/specify_cli/integrations/manifest.py +++ b/src/specify_cli/integrations/manifest.py @@ -451,7 +451,10 @@ def save(self) -> Path: _ensure_safe_manifest_destination(self.project_root, path) os.replace(temp_path, path) finally: - temp_path.unlink(missing_ok=True) + try: + temp_path.unlink(missing_ok=True) + except OSError: + pass return path @classmethod diff --git a/src/specify_cli/shared_infra.py b/src/specify_cli/shared_infra.py index 001a31e9e1..5585e1f86c 100644 --- a/src/specify_cli/shared_infra.py +++ b/src/specify_cli/shared_infra.py @@ -262,7 +262,10 @@ def _write_shared_bytes( _ensure_safe_shared_destination(project_path, dest) os.replace(temp_path, dest) finally: - temp_path.unlink(missing_ok=True) + try: + temp_path.unlink(missing_ok=True) + except OSError: + pass _BASH_FORMAT_COMMAND_RE = re.compile(