ZhuLinsen/daily_stock_analysis · error · ValueError
Hermes BASE_URL must not include params, query, or fragment
Error message
Hermes BASE_URL must not include params, query, or fragment
What it means
Purity check in canonicalize_hermes_base_url: parsed.params, parsed.query, or parsed.fragment must all be empty. The Hermes endpoint is fixed at the /v1 root; query strings (?key=...), fragments (#section), and params (;a=b) are not part of the contract and typically indicate a pasted documentation URL or an attempt to smuggle options/keys via the URL.
Source
Thrown at src/llm/hermes.py:175
def canonicalize_hermes_base_url(base_url: str) -> str:
"""Return canonical Hermes base URL or raise ValueError.
Allowed forms are loopback HTTP(S) URLs whose path is exactly /v1 or /v1/.
localhost is canonicalized to 127.0.0.1 to avoid DNS/hosts ambiguity.
"""
raw = (base_url or HERMES_DEFAULT_BASE_URL).strip() or HERMES_DEFAULT_BASE_URL
parsed = urlparse(raw)
if parsed.scheme.lower() not in {"http", "https"}:
raise ValueError("Hermes BASE_URL must use http or https")
if not parsed.netloc or not parsed.hostname:
raise ValueError("Hermes BASE_URL must include a loopback host")
if parsed.username or parsed.password:
raise ValueError("Hermes BASE_URL must not include userinfo")
if parsed.params or parsed.query or parsed.fragment:
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 excView on GitHub (pinned to 5159bd72e8)
Solutions
- Strip everything after the path: use exactly 'http://127.0.0.1:8642/v1'.
- Move any intended options into the proper config fields, not the URL.
Example fix
# before BASE_URL=http://127.0.0.1:8642/v1?api_key=abc # after BASE_URL=http://127.0.0.1:8642/v1
Defensive patterns
Strategy: validation
Validate before calling
parsed = urlparse(base_url) assert not (parsed.params or parsed.query or parsed.fragment), "strip query/fragment from BASE_URL"
Type guard
def url_is_bare(value: str) -> bool:
p = urlparse(value)
return not (p.params or p.query or p.fragment) Try / catch
try:
url = canonicalize_hermes_base_url(cfg.base_url)
except ValueError as exc:
raise ConfigError(str(exc)) from exc Prevention
- Do not paste doc-page URLs with query params into config
- Configure options via dedicated fields, never via URL query strings
When it happens
Trigger: BASE_URL like 'http://127.0.0.1:8642/v1?token=abc', 'http://127.0.0.1:8642/v1#chat', or copied from API docs that include example query parameters.
Common situations: Pasting a URL straight from provider docs (which often include ?api-version=... style params); attempting per-request configuration through the base URL.
Related errors
- Hermes BASE_URL must use http or https
- Hermes BASE_URL must include a loopback host
- Hermes BASE_URL must not include userinfo
- Hermes BASE_URL path must be /v1
- Hermes BASE_URL path must not contain encoded segments
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/c2f149474cc9561b.
Report an issue: GitHub.