From aa5fc1e6a5c831acf6d808327fdf6df765e64390 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Feb 2026 16:19:38 +0000 Subject: [PATCH 1/3] Initial plan From d92aff3dc49a18735235f2ef0872a3499600e81c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Feb 2026 16:24:30 +0000 Subject: [PATCH 2/3] Fix race condition in _do_download when scanning for .downloading files Co-authored-by: lstein <111189+lstein@users.noreply.github.com> --- .../app/services/download/download_default.py | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/invokeai/app/services/download/download_default.py b/invokeai/app/services/download/download_default.py index 9b5fda5620d..c5e487e324d 100644 --- a/invokeai/app/services/download/download_default.py +++ b/invokeai/app/services/download/download_default.py @@ -388,18 +388,23 @@ def _do_download(self, job: DownloadJob) -> None: if len(candidates) == 1: inferred = candidates[0].with_name(candidates[0].name.removesuffix(".downloading")) job.download_path = inferred - resume_from = candidates[0].stat().st_size - job.bytes = resume_from - self._logger.debug( - f"Resume check (dir): inferred in-progress file path={candidates[0]} size={resume_from} bytes" - ) - if resume_from > 0: - if job.etag: - header["If-Range"] = job.etag - elif job.last_modified: - header["If-Range"] = job.last_modified - header["Range"] = f"bytes={resume_from}-" - open_mode = "ab" + try: + resume_from = candidates[0].stat().st_size + except FileNotFoundError: + # The .downloading file was renamed/deleted between glob and stat (race condition); skip resume. + job.download_path = None + else: + job.bytes = resume_from + self._logger.debug( + f"Resume check (dir): inferred in-progress file path={candidates[0]} size={resume_from} bytes" + ) + if resume_from > 0: + if job.etag: + header["If-Range"] = job.etag + elif job.last_modified: + header["If-Range"] = job.last_modified + header["Range"] = f"bytes={resume_from}-" + open_mode = "ab" else: self._logger.debug( "Resume check (dir): no prior download_path available; cannot resume from disk " From 2e47004f240f267c232c8174d7a2c103e87cafbf Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Sat, 28 Feb 2026 11:33:28 -0500 Subject: [PATCH 3/3] chore(backend): update copyright --- invokeai/app/services/download/download_default.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/invokeai/app/services/download/download_default.py b/invokeai/app/services/download/download_default.py index c5e487e324d..f397e72cf48 100644 --- a/invokeai/app/services/download/download_default.py +++ b/invokeai/app/services/download/download_default.py @@ -1,4 +1,4 @@ -# Copyright (c) 2023, Lincoln D. Stein +# Copyright (c) 2023,2026 Lincoln D. Stein """Implementation of multithreaded download queue for invokeai.""" import os