Graphify-Labs/graphify · error · ValueError
OLLAMA_BASE_URL points at a link-local/metadata address ({ho
Error message
OLLAMA_BASE_URL points at a link-local/metadata address ({host!r}); refusing to send the corpus there. Set it to a real Ollama host. What it means
ValueError raised as an SSRF guard when OLLAMA_BASE_URL's host resolves to a link-local or cloud-metadata address (checked by _ollama_host_is_link_local_or_metadata, e.g. 169.254.x.x). graphify refuses to send the user's full corpus to such an endpoint. This is deliberately a hard stop, unlike the non-loopback warning printed right after.
Source
Thrown at graphify/llm.py:2810
parsed = urlparse(url)
except Exception:
if warn:
print(
f"[graphify] WARNING: OLLAMA_BASE_URL={url!r} is not a parseable URL.",
file=sys.stderr,
)
return
if parsed.scheme not in ("http", "https"):
if warn:
print(
f"[graphify] WARNING: OLLAMA_BASE_URL has unexpected scheme {parsed.scheme!r}; "
"expected http or https.",
file=sys.stderr,
)
return
host = (parsed.hostname or "").lower()
if _ollama_host_is_link_local_or_metadata(host):
raise ValueError(
f"OLLAMA_BASE_URL points at a link-local/metadata address ({host!r}); refusing to "
"send the corpus there. Set it to a real Ollama host."
)
is_loopback = host in ("localhost", "127.0.0.1", "::1") or host.startswith("127.")
if warn and not is_loopback:
scheme_note = " (UNENCRYPTED)" if parsed.scheme == "http" else ""
print(
f"[graphify] WARNING: OLLAMA_BASE_URL points to non-loopback host {host!r}{scheme_note}. "
"Your full corpus will be sent to that endpoint. "
"Set OLLAMA_BASE_URL=http://localhost:11434/v1 to keep extraction local.",
file=sys.stderr,
)
def detect_backend() -> str | None:
"""Return the name of whichever backend has an API key set, or None.
Priority: gemini → kimi → claude → openai → deepseek → azure → bedrock → ollama (last, opt-in).View on GitHub (pinned to 7fe58b0b0f)
Solutions
- Set OLLAMA_BASE_URL to the real Ollama host, e.g. export OLLAMA_BASE_URL='http://<real-ip>:11434/v1'.
- If you meant a local model: export OLLAMA_BASE_URL='http://localhost:11434/v1' - loopback is allowed.
- If the hostname legitimately resolves link-local (rare IPv6 fe80 setups), switch to the host's routable address instead.
Example fix
# before export OLLAMA_BASE_URL="http://169.254.169.254:11434/v1" # metadata IP $ graphify extract --backend ollama # ValueError: refused # after export OLLAMA_BASE_URL="http://192.168.1.20:11434/v1" # real Ollama host
Defensive patterns
Strategy: validation
Validate before calling
import ipaddress, socket
from urllib.parse import urlparse
url = "http://169.254.169.254:11434/v1" # your OLLAMA_BASE_URL
host = (urlparse(url).hostname or "").lower()
try:
for info in socket.getaddrinfo(host, None):
ip = ipaddress.ip_address(info[4][0])
if ip.is_link_local:
raise SystemExit(f"{host} resolves link-local ({ip}); fix OLLAMA_BASE_URL")
except socket.gaierror:
pass Try / catch
try:
validate_ollama_url(warn=True) # or the graphify entrypoint that reads OLLAMA_BASE_URL
except ValueError as exc:
if "link-local/metadata" in str(exc):
raise SystemExit("OLLAMA_BASE_URL targets a metadata/link-local IP - refusing") from exc
raise Prevention
- Never hardcode 169.254.169.254 in any URL but a deliberate metadata request.
- Prefer hostnames with stable routable DNS over raw IPs in base-URL config.
- Treat this guard as intentional - do not 'fix' it by disabling validation; fix the URL.
When it happens
Trigger: Validating OLLAMA_BASE_URL (with warn enabled) where the parsed hostname matches link-local (169.254.0.0/16, fe80::/10) or metadata addresses like 169.254.169.254 (llm.py:2806-2810). A common accident is a URL template substituting to http://169.254.169.254:11434/v1 or a misconfigured zero-config address.
Common situations: Config templating that injects the wrong IP; copying cloud-init metadata examples into OLLAMA_BASE_URL; on some networks mDNS/link-local resolution of 'ollama.local' landing in 169.254.x.x; confusion between the metadata IP and a real tailnet IP.
Related errors
- No LLM backend configured. Set one of: GEMINI_API_KEY, ANTHR
- No API key for backend '{backend}'. Set {_format_backend_env
- Azure OpenAI backend requires AZURE_OPENAI_ENDPOINT to be se
- No API key for backend '{backend}'. Set {_format_backend_env
- Azure OpenAI backend requires AZURE_OPENAI_ENDPOINT to be se
AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14).
Data as JSON: /api/errors/b2c4ea3537a2c45f.
Report an issue: GitHub.