langchain-ai/langchain · error · ValueError

Failed to resolve hostname

Error message

Failed to resolve hostname '{hostname}': {e}

What it means

`validate_safe_url` performs DNS resolution (`socket.getaddrinfo`) on the URL's hostname to inspect the resolved IPs; a `socket.gaierror` (name resolution failure) is wrapped in a `ValueError` with the hostname and OS error string. It means the hostname could not be resolved at validation time, before any request is made.

Solutions

  1. Verify the hostname resolves in the same environment: `python -c "import socket; print(socket.getaddrinfo('host', 80))"` from the same container/host
  2. Fix the hostname typo or use a fully-qualified domain name / IP literal where appropriate
  3. If offline validation is expected, skip or short-circuit SSRF validation for trusted internal URLs (e.g. `allow_private=True` plus pre-resolved IPs)
  4. Configure DNS in the container/deployment (e.g. `--dns`, CoreDNS, /etc/resolv.conf) so the name resolves

Example fix

# before
safe = validate_safe_url(f"http://{os.environ['WEBHOOK_HOST']}/cb")

# after
host = os.environ['WEBHOOK_HOST']
try:
    socket.gethostbyname(host)
except socket.gaierror:
    raise ValueError(f"WEBHOOK_HOST {host!r} does not resolve; check DNS config")
safe = validate_safe_url(f"http://{host}/cb")
Defensive patterns

Strategy: validation

Validate before calling

import socket

def hostname_resolves(hostname: str) -> bool:
    try:
        socket.getaddrinfo(hostname, 443, type=socket.SOCK_STREAM)
        return True
    except socket.gaierror:
        return False

if not hostname_resolves(parsed.hostname):
    raise ValueError(f"hostname {parsed.hostname!r} unresolvable; fix DNS")

Try / catch

try:
    safe = validate_safe_url(url)
except ValueError as e:
    if 'Failed to resolve hostname' in str(e):
        # config/DNS problem, not a policy block
        handle_dns_misconfig(url, e)
    else:
        raise

Prevention

When it happens

Trigger: Calling `validate_safe_url('http://nonexistent-host.example/x')` where DNS returns NXDOMAIN or SERVFAIL; typo'd hostnames; bare hostnames like `http://myapi/` that only resolve via search domains the process lacks; air-gapped/offline environments where the resolver is unreachable.

Common situations: Offline development machines or containers with no DNS; internal hostnames that resolve in one network but not another; typos in configured webhook/endpoint URLs; IPv6-only resolvers returning errors for AF_UNSPEC queries.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/b03288c63d7efc00. Report an issue: GitHub.

Appendix: source

Thrown at libs/core/langchain_core/_security/_ssrf_protection.py:102

    # DNS resolution and IP validation
    try:
        addr_info = socket.getaddrinfo(
            hostname,
            parsed.port or (443 if parsed.scheme == "https" else 80),
            socket.AF_UNSPEC,
            socket.SOCK_STREAM,
        )

        for result in addr_info:
            ip_str: str = result[4][0]  # type: ignore[assignment]
            try:
                _validate_resolved_ip(ip_str, policy)
            except SSRFBlockedError as exc:
                raise ValueError(str(exc)) from exc

    except socket.gaierror as e:
        msg = f"Failed to resolve hostname '{hostname}': {e}"
        raise ValueError(msg) from e
    except OSError as e:
        msg = f"Network error while validating URL: {e}"
        raise ValueError(msg) from e

    return url_str


def is_safe_url(
    url: str | AnyHttpUrl,
    *,
    allow_private: bool = False,
    allow_http: bool = True,
) -> bool:
    """Non-throwing version of `validate_safe_url`."""
    try:
        validate_safe_url(url, allow_private=allow_private, allow_http=allow_http)
    except ValueError:
        return False

View on GitHub (pinned to e32fa9a52e)