github/spec-kit · error · ExtensionError

Failed to download from {url}: {exc}

Error message

Failed to download from {url}: {exc}

What it means

The bounded (50 MiB) urllib download of the extension archive raised URLError, which is re-raised as an ExtensionError with the URL and cause. This covers every transport-level failure before any bytes can be validated: DNS, refused connections, timeouts, TLS errors, and HTTP error statuses surfaced by urllib.

Source

Thrown at src/specify_cli/extensions/_commands.py:160

        with dl_catalog._open_url(
            download_url, timeout=60, extra_headers=extra_headers
        ) as response:
            archive_data = read_response_limited(
                response,
                error_type=ExtensionError,
                label=f"extension {url}",
            )
            final_url = (
                response.geturl() if hasattr(response, "geturl") else download_url
            )
            content_type = (
                response.getheader("Content-Type")
                if hasattr(response, "getheader")
                else None
            )
    except urllib.error.URLError as exc:
        raise ExtensionError(f"Failed to download from {url}: {exc}") from exc

    download_fd = -1
    download_file = None
    try:
        try:
            download_fd = _safe_open_download_zip(
                project_root, download_dir, archive_filename
            )
        except OSError as exc:
            raise ExtensionError(
                f"Could not safely create download file: {exc}"
            ) from exc

        try:
            download_file = os.fdopen(download_fd, "w+b")
            download_fd = -1
            download_file.write(archive_data)
            download_file.flush()

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Reproduce outside the tool: `curl -vfL <url> -o /dev/null` and read the failure mode
  2. Regenerate expired pre-signed URLs or fix the 403/404 path
  3. For TLS issues: fix the certificate chain or export REQUESTS_CA_PACKAGE-equivalent trust (for urllib: SSL_CERT_FILE pointing at the proxy CA bundle)
  4. Download the archive manually with appropriate credentials, then install from the local file path

Example fix

# before
specify extension install https://github.com/org/repo/releases/download/v1/ext.zip  # 404: asset renamed

# after
specify extension install https://github.com/org/repo/releases/download/v1.0.0/my-ext.zip
# or download then install locally
curl -fL -o /tmp/my-ext.zip <url> && specify extension install /tmp/my-ext.zip
Defensive patterns

Strategy: retry

Validate before calling

import urllib.request

def url_downloadable(url: str) -> bool:
    try:
        req = urllib.request.Request(url, method='HEAD')
        with urllib.request.urlopen(req, timeout=5) as r:
            return r.status == 200
    except OSError:
        return False

Try / catch

from specify_cli.extensions import ExtensionError

try:
    manifest = install_from_url_cmd(project_root, url, speckit_version)
except ExtensionError as e:
    if str(e).startswith('Failed to download from'):
        # fallback: manual authenticated download, then install local path
        ...

Prevention

When it happens

Trigger: Running `specify extension install <url>` where the URL is unreachable, the TLS certificate is invalid/untrusted (common behind corporate MITM proxies), the server returns 403/404, or a slow host trips the timeout mid-transfer.

Common situations: Signed URL expired (common for pre-signed S3/GitHub release assets); private repo asset requiring auth the installer doesn't carry; CI environments with restricted egress; self-signed certs on internal hosts.

Related errors


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