unslothai/unsloth · error · ValueError

Provider base URL must contain a hostname.

Error message

Provider base URL must contain a hostname.

What it means

The URL parsed and has an http(s) scheme, but parts.hostname is empty — e.g. 'https:///v1' or 'https://:8080/v1'. Note the check runs after userinfo handling, so tricks like http://api.openai.com@169.254.169.254/ still yield the metadata IP as hostname and are caught by the later metadata check; this error is only for a genuinely absent host.

Source

Thrown at studio/backend/core/inference/providers.py:889

    raw = base_url.strip()
    if any(char.isspace() or ord(char) < 32 or ord(char) == 127 for char in raw) or "\\" in raw:
        raise ValueError("Provider base URL contains invalid characters.")

    try:
        parts = urlsplit(raw)
        port = parts.port
        hostname = parts.hostname
    except ValueError as exc:
        raise ValueError("Provider base URL is malformed.") from exc

    scheme = parts.scheme.lower()
    if scheme not in ("http", "https"):
        raise ValueError("Provider base URL must use http or https.")
    # Userinfo stays allowed for gateways behind basic auth; the checks below read
    # the parsed hostname, so http://api.openai.com@169.254.169.254/ is caught.
    if not hostname:
        raise ValueError("Provider base URL must contain a hostname.")

    hostname = hostname.rstrip(".")
    if _metadata_host(hostname) or _resolves_to_metadata(hostname, port, scheme):
        raise ValueError("Cloud metadata endpoints cannot be used as a provider base URL.")

    if os.environ.get(_BLOCK_PRIVATE_ENV) == "1":
        _reject_non_public(hostname, port, scheme)

    return raw.rstrip("/")


def list_available_providers(include_hidden: bool = False) -> list[dict[str, Any]]:
    """Return registered providers (for the /registry endpoint).

    Hidden entries exist only for backend lookups and are surfaced by the UI via
    ``CUSTOM_PROVIDER_PRESETS`` instead of the dropdown, so they stay filtered
    out by default. That default is load-bearing for upgrades: a browser holding
    a cached bundle from before this capability existed has no idea to filter on

View on GitHub (pinned to 203007d190)

Solutions

  1. Include the hostname: 'https://api.openai.com/v1'.
  2. Check templating/config interpolation for empty host variables.
  3. Validate presence of a host in client-side forms before submit.

Example fix

# before
validate_provider_base_url(f"https://{host}/v1")  # host == ""
# after
if not host:
    raise ValueError("host missing")
validate_provider_base_url(f"https://{host}/v1")
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlsplit
assert urlsplit(raw).hostname, "URL must include a hostname"

Type guard

def has_hostname(raw: str) -> bool:
    from urllib.parse import urlsplit
    return bool(urlsplit(raw).hostname)

Prevention

When it happens

Trigger: Base URLs with empty host: 'https:///v1', 'http://:9000/', or template-generated URLs where the host placeholder was never substituted.

Common situations: Config templating leaving {HOST} empty; users deleting the host while editing; constructing URLs by string concatenation with an empty host variable.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/10ff847aa15ad85e. Report an issue: GitHub.