ZhuLinsen/daily_stock_analysis · error · ValueError
Hermes BASE_URL contains an invalid port
Error message
Hermes BASE_URL contains an invalid port
What it means
Raised when urlsplit's parsed.port property throws while canonicalizing the Hermes BASE_URL. Python's port accessor raises ValueError when the port segment is non-numeric or outside 0-65535; this code wraps it into a clearer Hermes-specific ValueError. It is a strict config-format error raised before any network activity.
Source
Thrown at src/llm/hermes.py:193
raise ValueError("Hermes BASE_URL must not include params, query, or fragment")
raw_path = parsed.path or ""
decoded_path = unquote(raw_path)
if decoded_path not in {"/v1", "/v1/"}:
raise ValueError("Hermes BASE_URL path must be /v1")
if quote(decoded_path, safe="/") != raw_path.rstrip("/") and raw_path not in {"/v1", "/v1/"}:
raise ValueError("Hermes BASE_URL path must not contain encoded segments")
hostname = parsed.hostname.strip().lower()
if hostname == "localhost":
hostname = "127.0.0.1"
elif hostname not in {"127.0.0.1", "::1"}:
raise ValueError("Hermes BASE_URL must point to 127.0.0.1, localhost, or [::1]")
try:
port = parsed.port
except ValueError as exc:
raise ValueError("Hermes BASE_URL contains an invalid port") from exc
netloc = f"[{hostname}]" if ":" in hostname else hostname
if port is not None:
netloc = f"{netloc}:{port}"
return urlunparse(parsed._replace(netloc=netloc, path="/v1", params="", query="", fragment=""))
def canonicalize_hermes_model_ref(raw_model: str) -> HermesModelRef:
"""Return the canonical DSA route and LiteLLM wire model for Hermes.
Hermes is OpenAI-compatible over local HTTP, so both route identity and
outbound wire model use LiteLLM's openai/ namespace. The display label is
only UI metadata and must not be used for routing or provider detection.
"""
display_model = str(raw_model or "").strip() or HERMES_DEFAULT_MODEL
if display_model.startswith("openai/"):
canonical = display_modelView on GitHub (pinned to 5159bd72e8)
Solutions
- Correct the port to a plain integer between 1 and 65535, e.g. http://127.0.0.1:8080/v1
- Remove stray characters, spaces, or trailing punctuation from the netloc portion of the URL
- If the port comes from variable interpolation, print/render the final URL once during setup to catch substitution bugs
- Omit the port entirely when Hermes listens on the default port 80 so the parser never touches a port segment
Example fix
# before HERMES_BASE_URL=http://127.0.0.1:8080x/v1 # after HERMES_BASE_URL=http://127.0.0.1:8080/v1
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlsplit
def has_valid_port(url: str) -> bool:
try:
parsed = urlsplit(url)
parsed.port # raises ValueError on bad port
return True
except ValueError:
return False Try / catch
try:
url = canonicalize_hermes_base_url(raw)
except ValueError as exc:
if "port" in str(exc):
log.error("Fix HERMES_BASE_URL port: must be 1-65535")
raise Prevention
- Smoke-test the full URL (urlsplit + .port access) in a config sanity check before the app starts
- Generate URLs from host+port components instead of string concatenation
- Render the final interpolated URL in debug logs during setup
When it happens
Trigger: A BASE_URL like http://127.0.0.1:8080x/v1 (non-numeric port), http://127.0.0.1:99999/v1 (port above 65535), http://127.0.0.1:/v1 with stray characters, or a copy-paste artifact such as http://127.0.0.1:8080 /v1 that leaves a malformed netloc.
Common situations: Typos when hand-editing .env; port copied together with a colon or whitespace; using a URL with a service-port placeholder like <port> left unsubstituted; environment variable interpolation producing an empty-but-present malformed suffix.
Related errors
- Hermes BASE_URL must point to 127.0.0.1, localhost, or [::1]
- Responses API surface requires a normalized openai/<model> r
- LLM route aliases cannot mix API surfaces: {sorted(surface_c
- Hermes only supports PROTOCOL=openai
- unsafe_config
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/2c9ff2e3eed35873.
Report an issue: GitHub.