BerriAI/litellm · error · SSRFError
DNS resolution failed for
Error message
DNS resolution failed for '{hostname}': {e} What it means
SSRFError raised when socket.getaddrinfo fails for the URL's hostname during SSRF validation; the underlying socket.gaierror is embedded in the message. This is an environmental DNS failure (name does not exist, resolver unreachable), not a policy decision — it happens before any address can be checked against the block list.
Solutions
- From the proxy host, verify resolution: getent hosts <hostname> or dig <hostname>.
- Fix the hostname typo or point the URL at a resolvable name.
- For internal names, ensure the proxy's resolver can find them (DNS entry, search suffix, or hosts file).
- Catch SSRFError and surface a 'could not resolve host' 4xx/502 to the caller instead of a 500.
Example fix
# before
resp = safe_get(client, user_url) # unhandled SSRFError -> 500
# after
try:
resp = safe_get(client, user_url)
except SSRFError as e:
if "DNS resolution failed" in str(e):
raise HTTPException(status_code=400, detail="Could not resolve host in URL")
raise Defensive patterns
Strategy: try-catch
Validate before calling
import socket
def host_resolves(url: str) -> bool:
from urllib.parse import urlparse
host = urlparse(url).hostname
if not host:
return False
try:
socket.getaddrinfo(host, 443, proto=socket.IPPROTO_TCP)
return True
except socket.gaierror:
return False
if not host_resolves(user_url):
raise HTTPException(status_code=400, detail="URL host does not resolve") Try / catch
from litellm.litellm_core_utils.url_utils import SSRFError
try:
resp = safe_get(client, user_url)
except SSRFError as e:
if "DNS resolution failed" in str(e):
raise HTTPException(status_code=400, detail="Could not resolve host in URL")
raise Prevention
- Verify from the proxy host (not your laptop) that user-supplied domains resolve: getent hosts <name>.
- Monitor DNS health in the proxy container; gaierror often means resolver misconfiguration, not bad input.
- Surface DNS failures as 4xx to the caller so they can fix the URL.
When it happens
Trigger: Fetching a user URL whose host is typo'd or nonexistent (NXDOMAIN), a resolver outage in the container, an air-gapped or restricted network, or an internal hostname (.local, split-horizon name) the proxy's resolver cannot resolve.
Common situations: Self-hosted proxy deployments where the proxy pod uses different DNS than dev machines; expired domains in stored URLs; Kubernetes setups missing the internal DNS suffix.
Understand the failure class
- DNS resolution errors: ENOTFOUND and getaddrinfo failures — how hostname lookups fail and how to debug them.
Related errors
- No addresses found for
- Cisco AI Defense API request failed
- Compresr guardrail api_base has no host
- Compresr guardrail api_base must be http or https, got…
- Error fetching file
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/d44870ca28fa678b.
Report an issue: GitHub.
Appendix: 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 77b7c6c40c)