Graphify-Labs/graphify · warning · ValueError
DNS resolution failed for '{hostname}': {exc}. Got: {url!r}
Error message
DNS resolution failed for '{hostname}': {exc}. Got: {url!r} What it means
ValueError from validate_url when socket.getaddrinfo raises gaierror - the hostname does not resolve at all. Wrapped with `from exc` so the underlying resolver error (NXDOMAIN, timeout) stays in the chain. This is DNS failure rather than a policy block: the guard tries to check the IP but cannot get one.
Source
Thrown at graphify/security.py:139
if hostname.lower() in _BLOCKED_HOSTS:
raise ValueError(
f"Blocked cloud metadata endpoint '{hostname}'. "
f"Got: {url!r}"
)
# Resolve hostname and block private/reserved IP ranges
try:
infos = socket.getaddrinfo(hostname, None, socket.AF_UNSPEC, socket.SOCK_STREAM)
for info in infos:
addr = info[4][0]
ip = ipaddress.ip_address(addr)
if _ip_is_blocked(ip):
raise ValueError(
f"Blocked private/internal IP {addr} (resolved from '{hostname}'). "
f"Got: {url!r}"
)
except socket.gaierror as exc:
raise ValueError(
f"DNS resolution failed for '{hostname}': {exc}. Got: {url!r}"
) from exc
return url
# ---------------------------------------------------------------------------
# SSRF-guarded connections
#
# Instead of monkey-patching the process-global socket.getaddrinfo (a
# non-thread-safe TOCTOU hazard when multiple fetches run concurrently),
# we subclass the HTTP(S) connection so each connection resolves DNS exactly
# once, validates the resulting IP, and then connects to that exact IP. There
# is no second resolution, so a DNS-rebind attack cannot swap in a private
# address (e.g. 169.254.169.254) between validation and connection.
# ---------------------------------------------------------------------------
View on GitHub (pinned to 7fe58b0b0f)
Solutions
- Check the name resolves where graphify runs: `getent hosts <hostname>` or `python -c "import socket; print(socket.getaddrinfo('<hostname>', None))"`.
- Fix typos / use the canonical hostname.
- If it is an internal name, get on the right network/VPN or fix search-domain (resolv.conf search=) configuration.
- If DNS is flaky, retry - resolver timeouts masquerade as this error.
Example fix
# before url = 'https://api.exmaple.com/v1' # typo fetch(validate_url(url)) # ValueError: DNS resolution failed for 'api.exmaple.com' # after url = 'https://api.example.com/v1' fetch(validate_url(url))
Defensive patterns
Strategy: validation
Validate before calling
import socket
from urllib.parse import urlparse
host = urlparse(url).hostname or ""
try:
socket.getaddrinfo(host, None)
except socket.gaierror:
raise SystemExit(f"{host} does not resolve from this machine - fix DNS/VPN/name") Type guard
def is_safe_url(url: str) -> bool:
try:
validate_url(url)
return True
except ValueError:
return False Try / catch
try:
safe = validate_url(url)
except ValueError as exc:
if "DNS resolution failed" in str(exc):
return bad_request("hostname does not resolve") # user-fixable, 4xx
if "Blocked" in str(exc):
return forbidden(str(exc)) # policy, audit it
raise Prevention
- Preflight-resolve hostnames in config at deploy time so DNS drift is caught before runtime.
- In CI, assert VPN/peering with a getaddrinfo smoke test before URL-dependent jobs.
- Distinguish DNS failure from SSRF blocks in handlers - one is a 4xx user error, the other deserves an audit log.
When it happens
Trigger: validate_url(url) where the hostname fails DNS resolution from the machine running graphify (security.py:137-140): typo'd domains, split-horizon DNS where the name only exists internally, resolver outages, air-gapped CI, or .local mDNS names the resolver refuses.
Common situations: CI runners without VPN access fetching internal-only hostnames; typos like 'exmaple.com'; IPv6-only DNS quirks; systemd-resolved stub issues in containers; domains that exist publicly but not from restrictive resolvers.
Understand the failure class
- DNS resolution errors: ENOTFOUND and getaddrinfo failures — how hostname lookups fail and how to debug them.
Related errors
- Blocked private/internal IP {addr} (resolved from '{hostname
- ingest: {exc}
- ingest: failed to fetch {url!r}: {exc}
- Blocked URL scheme '{parsed.scheme}' - only http and https a
- Blocked cloud metadata endpoint '{hostname}'. Got: {url!r}
AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14).
Data as JSON: /api/errors/8c842bf824efa51c.
Report an issue: GitHub.