invoke-ai/InvokeAI · error · HTTPError

{reason}

Error message

{reason}

What it means

After the initial header request, if the response is not OK the library logs the remote host and status and raises requests' HTTPError with the response reason phrase. This branch handles the initial (non-resume) failure; statuses >= 500 are logged as 'Remote server error'. The reason string (e.g. 'Not Found', 'Forbidden') becomes the exception message.

Source

Thrown at invokeai/app/services/download/download_default.py:491

                job.total_bytes = expected
                job.expected_total_bytes = expected
                job.bytes = resume_from
                job.download_path = job.download_path or job.dest
                self._in_progress_path(job.download_path).rename(job.download_path)
                self._signal_job_started(job)
                self._signal_job_complete(job)
                return
            job.resume_required = True
            job.resume_message = "Resume refused by server. Restart required."
            job.pause()
            raise DownloadJobCancelledException("Resume refused by server. Restart required.")
        if not resp.ok:
            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)

        job.content_type = resp.headers.get("Content-Type")
        job.etag = resp.headers.get("ETag") or job.etag
        job.last_modified = resp.headers.get("Last-Modified") or job.last_modified
        content_length = int(resp.headers.get("content-length", 0))

        if job.dest.is_dir():
            parsed_url = urlparse(str(url))
            file_name = os.path.basename(parsed_url.path)  # default is to use the last bit of the URL

            if match := re.search('filename="(.+)"', resp.headers.get("Content-Disposition", "")):
                remote_name = match.group(1)
                if self._validate_filename(job.dest.as_posix(), remote_name):
                    file_name = remote_name

            # The URL path is attacker-influenced too -- a final segment of ".." would

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Read the logged 'Download failed from <host>: HTTP <status>' line to get the exact status and fix the root cause (fix URL, add auth header/token).
  2. For 5xx, retry with backoff — the failure is transient server-side.
  3. For 403/401, supply credentials: set the appropriate Authorization header via the job's request headers or HF token configuration.
  4. Verify the URL resolves in a browser / with `curl -I` and update the model listing or remote URL in your config.

Example fix

// before: bare URL without auth for a gated repo
queue.submit(HttpSource(url='https://huggingface.co/gated-model/weights.safetensors'), dest)

// after: pass an auth header with the job
headers = {'Authorization': f'Bearer {hf_token}'}
queue.submit(HttpSource(url='https://huggingface.co/gated-model/resolve/main/weights.safetensors', headers=headers), dest)
Defensive patterns

Strategy: try-catch

Validate before calling

import requests
r = requests.head(url, allow_redirects=True, timeout=10)
if r.status_code >= 400:
    raise SystemExit(f'URL unhealthy before submit: HTTP {r.status_code} {r.reason}')

Try / catch

try:
    queue.submit(HttpSource(url=url), dest)
except HTTPError as e:
    logger.error('download rejected: %s — check URL and auth', e)
except requests.exceptions.HTTPError as e:
    status = e.response.status_code if e.response is not None else None
    if status and status >= 500:
        retry_with_backoff()
    else:
        fix_url_or_credentials()

Prevention

When it happens

Trigger: The streaming GET in _do_download returns any 4xx/5xx status on the first request — 404 for a dead model URL, 403 for auth-gated repos, 429 rate limiting, or 5xx server faults.

Common situations: Typo'd or removed model file URL; downloading from Hugging Face gated repos without a token; corporate proxy returning 403/407; origin server overloaded (502/503) during large-model releases.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/70e59d5c4f095b98. Report an issue: GitHub.