BerriAI/litellm · error · SSRFError
DNS resolution failed for '{hostname}': {e}
Error message
DNS resolution failed for '{hostname}': {e} What it means
Raised by litellm's SSRF validator when socket.getaddrinfo fails with socket.gaierror while resolving the URL's hostname — i.e. DNS resolution itself failed (NXDOMAIN, resolver unreachable, temporary failure). The original gaierror text is embedded in the message. This is the network-level DNS error surfacing through the SSRF check, before any IP blocklist evaluation happens.
Source
Thrown at litellm/litellm_core_utils/url_utils.py:282
if parsed.scheme not in _ALLOWED_SCHEMES:
raise SSRFError(f"URL scheme '{parsed.scheme}' is not allowed")
hostname: Final = parsed.hostname
if not hostname:
raise SSRFError("URL has no hostname")
port: Final = parsed.port
default_port: Final = _default_port_for_scheme(parsed.scheme)
effective_port: Final = port if port is not None else default_port
host_header: Final = _format_host_header(hostname, effective_port, default_port)
is_allowlisted: Final = _is_host_allowlisted(hostname, effective_port)
# Resolve hostname and validate ALL addresses
try:
addrinfo: Final = socket.getaddrinfo(hostname, effective_port, proto=socket.IPPROTO_TCP)
except socket.gaierror as e:
raise SSRFError(f"DNS resolution failed for '{hostname}': {e}")
if not addrinfo:
raise SSRFError(f"No addresses found for '{hostname}'")
if not is_allowlisted:
for family, type_, proto, canonname, sockaddr in addrinfo:
resolved_ip = _sockaddr_host(sockaddr)
if _is_blocked_ip(resolved_ip):
raise SSRFError(
f"URL targets a blocked address ({resolved_ip}). "
"If this is a legitimate internal service, add the host "
"to `user_url_allowed_hosts` in general_settings."
)
# For HTTPS with SSL verification enabled, TLS certificate validation
# binds the connection to the hostname — DNS rebinding can't redirect
# to a different server because the cert wouldn't match.
# When SSL verification is disabled, this defense doesn't apply, soView on GitHub (pinned to 6c2dcb801b)
Solutions
- Verify DNS from the same environment the proxy runs in: python -c "import socket; print(socket.getaddrinfo('HOST', 443, proto=socket.IPPROTO_TCP))".
- Fix the hostname typo or switch to an IP/FQDN that resolves.
- If internal DNS is required, fix resolv.conf/dnsPolicy/CoreDNS so the litellm process can resolve the host.
- If the host legitimately has no public DNS, add it to user_url_allowed_hosts only after confirming the IPs are safe — note the allowlist skips IP checks, so use it deliberately.
Example fix
# before
safe_get(client, "https://api.mycompany-int.example.com/fetch") # NXDOMAIN
# after: verify DNS first, then use the resolvable internal name
import socket
assert socket.getaddrinfo("api.mycompany.internal", 443, proto=socket.IPPROTO_TCP)
safe_get(client, "https://api.mycompany.internal/fetch") Defensive patterns
Strategy: try-catch
Validate before calling
import socket
def resolves(hostname: str) -> bool:
try:
socket.getaddrinfo(hostname, 443, proto=socket.IPPROTO_TCP)
return True
except socket.gaierror:
return False Try / catch
from litellm.litellm_core_utils.url_utils import SSRFError
try:
resp = safe_get(client, url)
except SSRFError as e:
if "DNS resolution failed" in str(e):
return bad_request("hostname does not resolve from this environment")
raise Prevention
- Pre-flight resolve hostnames with socket.getaddrinfo from the same container/pod.
- Verify DNS config (resolv.conf, dnsPolicy) in deployments needing internal names.
- Distinguish DNS failures from blocklist hits in error handling — remediation differs.
When it happens
Trigger: validate_url('https://nonexistent-host.example.com/...') where the hostname does not resolve; DNS server down or unreachable in the container/pod; a hostname that only resolves on an internal DNS that the litellm process cannot reach; IPv6-only hostname with no AAAA record and broken resolver behavior.
Common situations: Typos in api_base hostnames; Kubernetes pods with misconfigured dnsPolicy; corporate DNS not available from the deployment environment; /etc/resolv.conf misconfiguration; hostnames that resolve in a browser (via search-domain fallback) but not via getaddrinfo.
Understand the failure class
- DNS resolution errors: ENOTFOUND and getaddrinfo failures — how hostname lookups fail and how to debug them.
Related errors
- Error listing files in '{directory_path}': {e}
- APIConnectionError: {exception_provider} - {error_str}
- getaddrinfo returned non-string host: {host!r}
- No addresses found for '{hostname}'
- URL targets a blocked address ({resolved_ip}). If this is a
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/d44870ca28fa678b.
Report an issue: GitHub.