langchain-ai/langchain · error · SSRFBlockedError

missing hostname

Error message

missing hostname

What it means

Raised by `validate_url_sync` when `urllib.parse.urlparse(url).hostname` is empty — the URL parses but has no host component, so hostname-level policy checks cannot run and the guard fails closed. Typical shapes are scheme-only URLs, opaque URIs, or relative paths where the authority component (`//host`) is absent.

Source

Thrown at libs/core/langchain_core/_security/_policy.py:297

    """Synchronous URL validation (no DNS resolution).

    Suitable for Pydantic validators and other sync contexts. Checks scheme
    and hostname patterns only - use `validate_url` for full DNS-aware checking.

    Raises:
        SSRFBlockedError: If the URL violates the policy.
    """
    parsed = urllib.parse.urlparse(url)

    scheme = (parsed.scheme or "").lower()
    if scheme not in policy.allowed_schemes:
        msg = f"scheme '{scheme}' not allowed"
        raise SSRFBlockedError(msg)

    hostname = parsed.hostname
    if not hostname:
        msg = "missing hostname"
        raise SSRFBlockedError(msg)

    allowed = _effective_allowed_hosts(policy)
    if hostname.lower() in {h.lower() for h in allowed}:
        return

    try:
        ipaddress.ip_address(hostname)
        validate_resolved_ip(hostname, policy)
    except SSRFBlockedError:
        raise
    except ValueError:
        pass
    else:
        return

    validate_hostname(hostname, policy)

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Fix the URL construction: ensure base URL is present and joined properly (`urljoin(base, path)`), producing e.g. `https://host/api/thing`.
  2. Reject host-less URLs at input validation (they are not fetchable anyway).
  3. If opaque schemes like mailto: are valid input for your field, validate them with a different rule instead of the SSRF fetch validator.

Example fix

# before
url = '/v1/chat'  # base URL lost
validate_url_sync(url, policy)  # missing hostname

# after
from urllib.parse import urljoin
url = urljoin('https://api.example.com', '/v1/chat')
validate_url_sync(url, policy)
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse

def has_hostname(url: str) -> bool:
    return bool(urlparse(url).hostname)

Try / catch

from langchain_core._security._policy import SSRFBlockedError

try:
    validate_url_sync(url, policy)
except SSRFBlockedError as e:
    if str(e) == "missing hostname":
        url = urljoin(settings.base_url, url)  # repair relative path and revalidate
        validate_url_sync(url, policy)
    else:
        raise

Prevention

When it happens

Trigger: `validate_url_sync('mailto:user@x.com')`, `validate_url_sync('/relative/path')`, `validate_url_sync('https:///path')` (empty authority), or `validate_url_sync('javascript:alert(1)')` after widening allowed_schemes. Note ordering: the scheme check runs first, so a non-allowed scheme on the same URL raises 'scheme ... not allowed' instead.

Common situations: Config/env-var URLs missing the host ('https:///api'), relative endpoint paths concatenated in the wrong order (base omitted), or user input like an email `mailto:` link fed into a URL-fetch validator. Also common in tests using path-only fixtures.

Related errors


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