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
- Reproduce outside the tool: `curl -vfL <url> -o /dev/null` and read the failure mode
- Regenerate expired pre-signed URLs or fix the 403/404 path
- 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)
- 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
- Use fresh pre-signed URLs at install time; treat them as short-lived
- Keep a manual curl + local-path install as the fallback playbook for auth-gated artifacts
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
- Failed to fetch catalog from {entry.url}: {e}
- Failed to fetch catalog from {catalog_url}: {e}
- ERROR: Feature directory not found. Set SPECIFY_FEATURE_DIRE
- Invalid extension registry {registry}: not a regular file
- Network access disabled; cannot download bundle '{resolved.e
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/d12e8861d062153c.
Report an issue: GitHub.