BerriAI/litellm · error · SSRFError

No addresses found for

Error message

No addresses found for '{hostname}'

What it means

SSRFError raised when getaddrinfo returns success but an empty address list for the hostname — a rare resolver state in which the name yields no usable A/AAAA records at all. The guard exists so the subsequent per-address block check cannot silently skip an empty result.

Solutions

  1. Check what the name actually resolves to from the proxy host: getent ahostsv4 <hostname> or dig A + AAAA.
  2. If there are no address records, fix the DNS entry or change the URL to a name with A/AAAA records.
  3. Retry once — empty answers can be transient — then fail with a clear message.

Example fix

# before
resp = safe_get(client, user_url)  # SSRFError: No addresses found for 'host'

# after
try:
    resp = safe_get(client, user_url)
except SSRFError as e:
    if "No addresses found" in str(e):
        raise HTTPException(status_code=400, detail="URL host has no resolvable addresses")
    raise
Defensive patterns

Strategy: try-catch

Validate before calling

import socket

def host_has_addresses(url: str) -> bool:
    from urllib.parse import urlparse
    host = urlparse(url).hostname
    if not host:
        return False
    try:
        return bool(socket.getaddrinfo(host, 443, proto=socket.IPPROTO_TCP))
    except socket.gaierror:
        return False

Try / catch

from litellm.litellm_core_utils.url_utils import SSRFError

try:
    resp = safe_get(client, user_url)
except SSRFError as e:
    if "No addresses found" in str(e):
        raise HTTPException(status_code=400, detail="URL host has no resolvable addresses")
    raise

Prevention

When it happens

Trigger: DNS names whose only records are types getaddrinfo does not return for TCP lookups, misconfigured resolvers, or transient resolver glitches in containers.

Common situations: Rare; occasionally seen with broken split-horizon DNS or names that exist in DNS metadata but have no address records.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/411684a5fc5cbf61. Report an issue: GitHub.

Appendix: source

Thrown at litellm/litellm_core_utils/url_utils.py:285

    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, so
    # we rewrite to the validated IP like HTTP.
    ssl_verify: Final = getattr(litellm, "ssl_verify", True)
    if parsed.scheme == "https" and ssl_verify is not False:

View on GitHub (pinned to 77b7c6c40c)