github/spec-kit · error · PresetError
Failed to fetch preset catalog from {entry.url}: {e}
Error message
Failed to fetch preset catalog from {entry.url}: {e} What it means
Fetching a preset catalog over HTTP failed. The per-catalog fetch (redirect-validated open, size-limited read, JSON parse, payload validation) wraps any non-PresetError exception — URLError, timeout, JSONDecodeError, ImportError — into PresetError; existing PresetErrors (e.g. payload validation failures) are re-raised unchanged.
Source
Thrown at src/specify_cli/presets/__init__.py:4542
cache_file.write_text(
json.dumps(catalog_data, indent=2), encoding="utf-8"
)
metadata = {
"cached_at": datetime.now(timezone.utc).isoformat(),
"catalog_url": entry.url,
}
metadata_file.write_text(
json.dumps(metadata, indent=2), encoding="utf-8"
)
except OSError:
pass # Cache is best-effort; proceed with fetched data
return catalog_data
except (ImportError, Exception) as e:
if isinstance(e, PresetError):
raise
raise PresetError(
f"Failed to fetch preset catalog from {entry.url}: {e}"
)
def _get_merged_packs(self, force_refresh: bool = False) -> Dict[str, Dict[str, Any]]:
"""Fetch and merge presets from all active catalogs.
Higher-priority catalogs (lower priority number) win on ID conflicts.
Returns:
Merged dictionary of pack_id -> pack_data
"""
active_catalogs = self.get_active_catalogs()
merged: Dict[str, Dict[str, Any]] = {}
for entry in reversed(active_catalogs):
try:
data = self._fetch_single_catalog(entry, force_refresh)
for pack_id, pack_data in data.get("presets", {}).items():View on GitHub (pinned to bf88c9f9a8)
Solutions
- Check network reachability of the catalog URL (curl -I <url>) and fix proxy/DNS issues
- Verify the URL in the catalog config is correct and serves valid JSON under the size limit
- If behind a corporate proxy, configure proxy env vars (HTTPS_PROXY) so urllib can connect
- If the catalog redirect is rejected, update the config to the final HTTPS URL directly
- Retry after transient outages; clear the preset cache to force a clean refetch
Defensive patterns
Strategy: retry
Validate before calling
import urllib.request, json
req = urllib.request.Request(entry.url, method="HEAD")
with urllib.request.urlopen(req, timeout=10) as r:
reachable = 200 <= r.status < 400 # preflight before invoking fetch Try / catch
from specify_cli.presets import PresetError
for attempt in range(3):
try:
data = manager._fetch_catalog(entry)
break
except PresetError as e:
if attempt == 2 or "Failed to fetch" not in str(e):
raise
time.sleep(2 ** attempt) # transient network errors only Prevention
- Keep catalogs on reliable HTTPS hosts and pin final URLs (avoid redirect chains)
- Use cached data when fetch fails instead of hard-failing, if your flow allows
- Set proxy env vars in corporate networks so urllib can reach the host
When it happens
Trigger: Calling _fetch_catalog(entry) when the catalog URL is unreachable (DNS failure, connection refused, timeout after 10s), returns invalid JSON or an oversized body (>MAX_JSON_CATALOG_BYTES), redirects to a URL that fails _validate_catalog_url, or when a required import is missing.
Common situations: Offline machine or corporate proxy blocking the catalog host; catalog server down or returning an HTML error page; typo'd catalog URL in config; redirect to HTTP or disallowed host being rejected by the security validator.
Related errors
- Failed to fetch preset catalog from {catalog_url}: {e}
- Failed to download preset from {download_url}: {e}
- Failed to download bundle '{entry_id}' from {_source_desc}:
- Could not query extension catalog: {catalog_error}
- Failed to fetch catalog from {entry.url}: {e}
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/8704d997412e0d3b.
Report an issue: GitHub.