github/spec-kit · error · BundlerError

Refusing to download {label} from URL with no host: {url}

Error message

Refusing to download {label} from URL with no host: {url}

What it means

After the scheme check passes, Spec Kit requires the download URL to contain a hostname. URLs such as `https:///bundle.zip` or `https://:8443/bundle.zip` have no authority and are rejected as BundlerError. This prevents an ambiguous, scheme-only URL from reaching the downloader.

Source

Thrown at src/specify_cli/commands/bundle/__init__.py:927

    # urlparse / hostname access raise ValueError on a malformed authority;
    # keep the documented BundlerError contract (older Pythons surface this via
    # the .hostname access below rather than at the urlparse call).
    try:
        parsed = urlparse(url)
        hostname = parsed.hostname
        # Accessing ``port`` performs urllib's syntax/range validation.
        _ = parsed.port
    except ValueError:
        raise BundlerError(
            f"Refusing to download {label}: 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 BundlerError(
            f"Refusing to download {label} over non-HTTPS URL: {url}"
        )
    if not parsed.hostname:
        raise BundlerError(f"Refusing to download {label} from URL with no host: {url}")


def _download_remote_manifest(
    entry_id: str,
    url: str,
    *,
    expected_sha256: str | None = None,
):
    """Fetch a remote bundle artifact over HTTPS and extract its manifest."""
    import io
    import tempfile
    from pathlib import PurePosixPath
    from urllib.parse import urlparse as _urlparse

    import yaml as _yaml

    from ...authentication.http import github_provider_hosts, open_url
    from ..._github_http import resolve_github_release_asset_api_url

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Inspect the URL in the message and add the missing hostname, for example `https://example.com/downloads/bundle.zip`.
  2. Check how the catalog download_url is generated if it is produced from variables or a template.
  3. If the bad URL is a redirect/final URL, fix the server's Location header and retry.

Example fix

# before
"download_url": "https:///bundles/my-bundle.zip"

# after
"download_url": "https://catalog.example.com/bundles/my-bundle.zip"
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse

def url_has_https_host(url: str) -> bool:
    try:
        p = urlparse(url)
        _ = p.port
    except ValueError:
        return False
    return p.scheme == "https" and bool(p.hostname)

Try / catch

except BundlerError as exc:
    if "URL with no host" in str(exc):
        reject_catalog_entry_with_empty_host()
    else:
        raise

Prevention

When it happens

Trigger: A catalog entry, redirect target, or final response URL uses HTTPS but omits or empties the host component, for example `https:///downloads/bundle.zip`.

Common situations: A catalog URL was assembled by string concatenation and the host variable was empty. Someone deleted the host while editing a URL, or a reverse proxy emitted a Location header without a host.

Related errors


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