unslothai/unsloth · error · ValueError
Provider base URL points at a private address, which is disa
Error message
Provider base URL points at a private address, which is disabled on this server (UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS=1).
What it means
Raised when UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS=1 and the resolved addresses of the provider base URL include a non-global IP (loopback, LAN, link-local, or an empty resolution list). This is an opt-in SSRF hardening: the backend sends the caller's decrypted API key to this URL, so private targets are refused. Plain http, odd ports, and userinfo remain allowed — only address reachability class is checked.
Source
Thrown at studio/backend/core/inference/providers.py:848
if resolved is None:
# This path blocked on an unbounded getaddrinfo before the metadata
# check existed, and a resolver slower than that check's deadline is
# ordinary (the Linux default is 5s per server, twice). Falling back
# to the same unbounded call keeps a slow-but-working resolver from
# turning into a refusal here, where "no answer" fails closed.
import socket
try:
infos = socket.getaddrinfo(
_transport_host(hostname),
port or (443 if scheme == "https" else 80),
type = socket.SOCK_STREAM,
)
except (OSError, UnicodeError) as exc:
raise ValueError("Provider base URL hostname could not be resolved.") from exc
resolved = tuple(str(info[4][0]) for info in infos)
addresses = [ipaddress.ip_address(address.split("%", 1)[0]) for address in resolved]
if not addresses or any(not ip.is_global for ip in addresses):
raise ValueError(
"Provider base URL points at a private address, which is disabled on this "
f"server ({_BLOCK_PRIVATE_ENV}=1)."
)
def validate_provider_base_url(base_url: str) -> str:
"""Return a normalized provider base URL, or raise ``ValueError``.
The backend issues outbound requests to this URL with the caller's decrypted
API key attached, so it is caller-controlled server-side egress. Only shapes
that can never be a real provider endpoint are refused: a non-http(s) scheme,
control characters, a missing host, and cloud metadata services. Plain http,
loopback, LAN hosts, odd ports, query strings and basic-auth userinfo all
stay valid -- Ollama, llama.cpp, vLLM and custom gateways rely on them. A
caller-supplied hostname is resolved far enough to apply the metadata block
to DNS aliases of it; rejecting other private addresses stays opt-in.
Normalization is strip + trailing-slash removal only (what the client didView on GitHub (pinned to 203007d190)
Solutions
- If the private endpoint is intentional and trusted, unset UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS (or set to 0) — the check is explicitly opt-in.
- Otherwise point the base URL at a genuinely public provider endpoint.
- If a public hostname resolves privately (split-horizon DNS), use an endpoint that resolves publicly from this host.
- Document which environments run with the flag on so LAN gateways are not configured there.
Example fix
# before (flag on, LAN gateway refused)
validate_provider_base_url("http://192.168.1.10:11434/v1")
# after (trust the LAN gateway)
# export UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS=0
validate_provider_base_url("http://192.168.1.10:11434/v1") Defensive patterns
Strategy: validation
Validate before calling
import ipaddress, socket, os
def url_is_public(url: str) -> bool:
from urllib.parse import urlsplit
h = urlsplit(url).hostname
if not h:
return False
try:
infos = socket.getaddrinfo(h, None, type=socket.SOCK_STREAM)
except OSError:
return False
return all(ipaddress.ip_address(i[4][0]).is_global for i in infos) Try / catch
try:
validate_provider_base_url(url)
except ValueError as e:
if "private address" in str(e):
if trusted_internal_gateway(url):
os.environ.pop("UNSLOTH_STUDIO_BLOCK_PRIVATE_PROVIDER_URLS")
url = validate_provider_base_url(url) Prevention
- Decide per-deployment whether the private-URL block should be on; document it.
- Never point production instances (flag on) at LAN gateways — they will be refused by design.
- Watch for split-horizon DNS where public names resolve privately on the server.
When it happens
Trigger: Setting a provider base URL to http://192.168.1.10:11434/v1 (Ollama), http://localhost:8080 (llama.cpp), or a public name that resolves to a private IP while the block env var is set to 1.
Common situations: Self-hosted studios pointing at LAN LLM servers with the hardening flag inherited from a public deployment config; DNS rebinding where a public hostname resolves internally; 169.254.x addresses.
Related errors
- Provider base URL hostname could not be resolved.
- {_cn_fs.reason}
- Provider base URL is required.
- Provider base URL contains invalid characters.
- Provider base URL is malformed.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/44b218d47810be9a.
Report an issue: GitHub.