invoke-ai/InvokeAI · info · DownloadJobCancelledException
Job was cancelled at caller's request
Error message
Job was cancelled at caller's request
What it means
Inside the streaming download loop, each chunk first checks job.cancelled. If the caller requested cancellation (via the queue's cancel API), the loop aborts immediately by raising DownloadJobCancelledException('Job was cancelled at caller's request'). The partial `.downloading` file is left in place so a later resume can continue from the last chunk. This is expected control flow, not a malfunction.
Source
Thrown at invokeai/app/services/download/download_default.py:608
elif resp.status_code != 200:
host = urlparse(str(resp.url or url)).netloc
status = resp.status_code
reason = resp.reason
if status >= 500:
self._logger.error(f"Remote server error from {host}: HTTP {status} {reason}")
raise HTTPError(reason)
self._logger.error(f"Download failed from {host}: HTTP {status} {reason}")
raise HTTPError(reason)
self._logger.debug(f"{job.source}: Downloading {job.download_path}")
report_delta = job.total_bytes / 100 # report every 1% change
last_report_bytes = 0
# DOWNLOAD LOOP
with open(in_progress_path, open_mode) as file:
for data in resp.iter_content(chunk_size=DOWNLOAD_CHUNK_SIZE):
if job.cancelled:
raise DownloadJobCancelledException("Job was cancelled at caller's request")
job.bytes += file.write(data)
if (job.bytes - last_report_bytes >= report_delta) or (job.bytes >= job.total_bytes):
last_report_bytes = job.bytes
self._signal_job_progress(job)
if job.total_bytes > 0 and job.bytes < job.total_bytes:
job.resume_required = True
job.resume_message = "Download interrupted. Resume required."
job.pause()
raise DownloadJobCancelledException("Download interrupted. Resume required.")
# if we get here we are done and can rename the file to the original dest
self._logger.debug(f"{job.source}: saved to {job.download_path} (bytes={job.bytes})")
in_progress_path.rename(job.download_path)
def _validate_url(self, url: str) -> None:
"""Refuse to fetch URLs that point at addresses only the server can reach."""View on GitHub (pinned to 0b6a024f2f)
Solutions
- No fix needed: handle DownloadJobCancelledException as a normal cancellation; the partial `.downloading` file supports later resume.
- If the cancellation was unintentional, resume the job — it continues from job.bytes without redownloading everything.
- During shutdown, wait for jobs or call the queue's graceful-stop API instead of hard-cancel to finish small downloads.
- Clean up orphaned `.downloading` files only if you never intend to resume.
Example fix
// before: treating cancellation as fatal
try:
queue.join()
except Exception as e:
logger.critical(e)
// after: distinguish cancellation
try:
queue.join()
except DownloadJobCancelledException:
logger.info('download cancelled; resumable later') Defensive patterns
Strategy: try-catch
Validate before calling
# check before cancelling whether the job is nearly done
if job.total_bytes and (job.bytes / job.total_bytes) > 0.98:
queue.join(job.id) # let it finish instead of cancelling
else:
queue.cancel(job.id) Try / catch
try:
queue.join()
except DownloadJobCancelledException as e:
if "caller's request" in str(e):
logger.info('job cancelled by user; partial .downloading kept for resume')
else:
logger.warning('job paused for other reason: %s', e) Prevention
- Treat DownloadJobCancelledException as expected flow — never log it as a crash.
- Check job.cancelled proactively in UI-driven flows before resuming.
- Preserve `.downloading` partials so cancelled downloads resume cheaply.
- On shutdown, prefer graceful queue stop over immediate cancel for near-complete jobs.
When it happens
Trigger: Calling RemoteDownloadService.cancel(job_id) — or cancelling the source/queue — while bytes are actively streaming in _do_download's iter_content loop.
Common situations: User cancels a slow large-model download from the UI; app shutdown drains the queue and cancels in-flight jobs; a script aborts a download after a timeout; duplicate job cancelled in favor of another.
Related errors
- Job was cancelled before start
- Download interrupted. Resume required.
- Unexpected error while canceling all except current: {e}
- Attempt to start the download service twice
- The download service is not currently accepting requests. Pl
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/8c61d34a1b9a2339.
Report an issue: GitHub.