github/spec-kit · error · PresetError

Failed to download preset from {download_url}: {e}

Error message

Failed to download preset from {download_url}: {e}

What it means

The archive download failed at the HTTP/URL layer: urllib.error.URLError (and its HTTPError subclass) raised while opening or reading the download stream. It is wrapped into PresetError with the source URL; note URLError is a subclass of OSError, but it is caught before the IOError branch.

Source

Thrown at src/specify_cli/presets/__init__.py:4955

                    else original_download_url
                ),
                content_type=content_type,
                error_type=PresetError,
            )
            archive_path = build_safe_download_path(
                target_dir,
                pack_id,
                version,
                error_type=PresetError,
                label="preset",
                suffix=archive_suffix(archive_format),
            )
            os.replace(staging_path, archive_path)
            staging_path = None
            return archive_path

        except urllib.error.URLError as e:
            raise PresetError(
                f"Failed to download preset from {download_url}: {e}"
            )
        except IOError as e:
            raise PresetError(f"Failed to save preset archive: {e}")
        finally:
            if staging_path is not None:
                staging_path.unlink(missing_ok=True)

    def clear_cache(self):
        """Clear all catalog cache files, including per-URL hashed caches."""
        if self.cache_dir.exists():
            for f in self.cache_dir.iterdir():
                if f.is_file() and f.name.startswith("catalog"):
                    f.unlink(missing_ok=True)


class PresetResolver:
    """Resolves template names to file paths using a priority stack.

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Fetch the URL manually (curl -fSL <download_url>) to see the concrete HTTP/network error
  2. If 404/410, refresh the catalog so download_url points at the current artifact, or pin a version that still exists
  3. Fix proxy/certificate environment issues (HTTPS_PROXY, CA bundle) for the artifact host
  4. Retry after transient failures — the download is not cached until it fully succeeds (staging file is unlinked in finally)
Defensive patterns

Strategy: retry

Validate before calling

import urllib.request
req = urllib.request.Request(download_url, method="HEAD")
try:
    with urllib.request.urlopen(req, timeout=10) as r:
        downloadable = 200 <= r.status < 400
except OSError:
    downloadable = False  # preflight before the real download

Try / catch

for attempt in range(3):
    try:
        archive = manager.download_preset_archive(pack_id)
        break
    except PresetError as e:
        if attempt == 2 or "Failed to download" not in str(e):
            raise
        time.sleep(2 ** attempt)  # transient URLError/HTTPError only

Prevention

When it happens

Trigger: download_preset_archive when the download host is unreachable, the connection times out, TLS fails, or the server returns 4xx/5xx (HTTPError) — after all URL validations passed.

Common situations: Catalog reachable but artifact host (CDN, release bucket) down or moved; 404 because the versioned archive was deleted/renamed; proxy/firewall blocking the download domain; expired token in a signed URL.

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/39bce044a4d9dcb4. Report an issue: GitHub.