oobabooga/textgen · error · ValueError

Could not resolve hostname: {hostname}

Error message

Could not resolve hostname: {hostname}

What it means

Raised by _validate_url() when socket.getaddrinfo() raises socket.gaierror while resolving the URL hostname — i.e. DNS lookup failed (NXDOMAIN, no resolver, offline, or malformed host). The guard must resolve the host to check it against private ranges, so an unresolvable name is treated as invalid rather than being passed through to the HTTP client.

Source

Thrown at modules/web_search.py:40

    parsed = urlparse(url)
    if parsed.scheme not in ('http', 'https'):
        raise ValueError(f"Unsupported URL scheme: {parsed.scheme}")

    if '@' in parsed.netloc:
        raise ValueError("Invalid URL: userinfo (credentials) in URLs is not allowed")

    hostname = parsed.hostname
    if not hostname:
        raise ValueError("No hostname in URL")

    # Resolve hostname and check all returned addresses
    try:
        for family, _, _, _, sockaddr in socket.getaddrinfo(hostname, None):
            ip = ipaddress.ip_address(sockaddr[0])
            if not ip.is_global:
                raise ValueError(f"Access to non-public address {ip} is blocked")
    except socket.gaierror:
        raise ValueError(f"Could not resolve hostname: {hostname}")


def safe_get(url, headers=None, timeout=10, max_redirects=5):
    """Fetch a URL with SSRF-safe redirect handling. Validates every hop."""
    _validate_url(url)
    for _ in range(max_redirects):
        response = requests.get(url, headers=headers, timeout=timeout, allow_redirects=False)
        if response.is_redirect and 'Location' in response.headers:
            url = urljoin(url, response.headers['Location'])
            _validate_url(url)
        else:
            return response

    raise ValueError(f"Too many redirects (max {max_redirects})")


def get_current_timestamp():
    """Returns the current time in 24-hour format"""

View on GitHub (pinned to ed888c71f2)

Solutions

  1. Verify the hostname with dig/getent hosts <host> from the same machine/container the app runs on.
  2. Fix typos or use a different mirror for dead domains.
  3. If in a container, ensure it has working DNS (docker --dns, correct resolv.conf).
  4. Retry once after a transient resolver blip, but stop and report if it persists.
Defensive patterns

Strategy: retry

Validate before calling

import socket
from urllib.parse import urlparse

def hostname_resolves(url: str) -> bool:
    host = urlparse(url).hostname
    if not host:
        return False
    try:
        socket.getaddrinfo(host, None)
        return True
    except socket.gaierror:
        return False

Try / catch

import socket

for attempt in range(2):  # one retry for transient resolver blips
    try:
        resp = safe_get(url)
        break
    except ValueError as e:
        if 'Could not resolve hostname' in str(e) and attempt == 0:
            continue
        raise

Prevention

When it happens

Trigger: Fetching a URL with a typo'd or non-existent domain ('https://exmaple.com'), a host only resolvable on an internal DNS the process cannot reach, running in a sandbox/container without network access, or a transient resolver failure.

Common situations: Typos in hostnames; expired/dead domains in search results or feeds; air-gapped or DNS-restricted containers; VPN split-DNS where the name only resolves inside the VPN but the process runs outside it.

Understand the failure class

Related errors


AI-assisted analysis of oobabooga/textgen@ed888c71f2 (2026-08-15). Data as JSON: /api/errors/4dc2f81936167b32. Report an issue: GitHub.