github/spec-kit · error · PresetValidationError
Catalog URL must use HTTPS (got {parsed.scheme}://). HTTP is
Error message
Catalog URL must use HTTPS (got {parsed.scheme}://). HTTP is only allowed for localhost. What it means
Catalog URLs must use HTTPS, with a single exception: plain HTTP is allowed for localhost (hostname exactly localhost, 127.0.0.1, or ::1). Any other scheme — http against a remote host, ftp, file — fails this PresetValidationError. This exists because catalog fetches send auth headers and must not leak over plaintext connections.
Source
Thrown at src/specify_cli/presets/__init__.py:4156
Args:
url: URL to validate
Raises:
PresetValidationError: If URL is invalid or uses non-HTTPS scheme
"""
from urllib.parse import urlparse
try:
parsed = urlparse(url)
hostname = parsed.hostname
except ValueError:
raise PresetValidationError(f"Catalog URL is malformed: {url}") from None
is_localhost = hostname in ("localhost", "127.0.0.1", "::1")
if parsed.scheme != "https" and not (
parsed.scheme == "http" and is_localhost
):
raise PresetValidationError(
f"Catalog URL must use HTTPS (got {parsed.scheme}://). "
"HTTP is only allowed for localhost."
)
# Check hostname, not netloc: netloc is truthy for host-less URLs like
# "https://:8080" or "https://user@", so the host guarantee this error
# promises would not actually hold. hostname is None in those cases (#3209).
if not hostname:
raise PresetValidationError(
"Catalog URL must be a valid URL with a host."
)
def _make_request(self, url: str):
"""Build a urllib Request, adding auth headers when a provider matches.
Delegates to :func:`specify_cli.authentication.http.build_request`.
"""
from specify_cli.authentication.http import build_request
return build_request(url)View on GitHub (pinned to bf88c9f9a8)
Solutions
- Serve the catalog over HTTPS (put it behind TLS or a proxy) and use the https:// URL.
- For local development, keep the host literal: http://localhost:8000, http://127.0.0.1:8000, or http://[::1]:8000.
- If you use a hostname alias for localhost, switch to the literal 127.0.0.1 to stay within the exception.
Example fix
# before catalogs: - url: "http://catalog.internal/catalog.json" # after catalogs: - url: "https://catalog.internal/catalog.json"
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
p = urlparse(url)
host = p.hostname
assert p.scheme == "https" or (p.scheme == "http" and host in ("localhost", "127.0.0.1", "::1")), \
"catalog URL must be https (http only for localhost)" Type guard
from urllib.parse import urlparse
def is_allowed_catalog_url(url: str) -> bool:
try:
p = urlparse(url)
except ValueError:
return False
return p.scheme == "https" or (p.scheme == "http" and p.hostname in ("localhost", "127.0.0.1", "::1")) Try / catch
try:
manager.add_catalog(url)
except PresetValidationError as e:
if "must use HTTPS" in str(e):
# switch the entry to https, or use a literal localhost host for dev
... Prevention
- Default every catalog entry to https://.
- Local dev: keep http://localhost, http://127.0.0.1, or http://[::1] literally — hostname aliases are not exempt.
- Auth headers are attached to catalog requests; never point them at plain-HTTP remote hosts.
When it happens
Trigger: Configuring a catalog entry with `http://internal.example.com/catalog.json` (remote HTTP), `ftp://...`, or an http:// URL whose host is a machine name or 0.0.0.0 (not in the localhost allowlist). Note: only the literal hostname counts — `http://127.0.0.1.nip.io` is rejected.
Common situations: Pointing at an internal/staging catalog served over plain HTTP inside a VPN, or a local dev server bound to a LAN hostname instead of localhost.
Related errors
- Catalog url must use HTTPS (got {parsed.scheme}://). HTTP is
- Catalog entry '{resolved.entry.id}' has a non-HTTP(S) downlo
- Refusing to download {label} over non-HTTPS URL: {url}
- Preset '{component.id}' not found in any catalog.
- Preset '{component.id}' is from a discovery-only catalog; in
AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14).
Data as JSON: /api/errors/1fde6560a4ca9dc3.
Report an issue: GitHub.