{"record":{"id":"1a7dcd6dd1697996","repo":"NousResearch/hermes-agent","slug":"malformed-custom-endpoint-url-candidate-r-run","errorCode":null,"errorMessage":"Malformed custom endpoint URL: {candidate!r}. Run `hermes setup` or `hermes model` and enter a valid http(s) base URL.","messagePattern":"Malformed custom endpoint URL: (.+?)\\. Run `hermes setup` or `hermes model` and enter a valid http\\(s\\) base URL\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agent/auxiliary_client.py","lineNumber":3549,"sourceCode":"            raise RuntimeError(\n                f\"Malformed proxy environment variable {key}={value!r}. \"\n                \"Fix or unset your proxy settings and try again.\"\n            ) from exc\n\n\ndef _validate_base_url(base_url: str) -> None:\n    \"\"\"Reject obviously broken custom endpoint URLs before they reach httpx.\"\"\"\n    from urllib.parse import urlparse\n\n    candidate = str(base_url or \"\").strip()\n    if not candidate or candidate.startswith(\"acp://\"):\n        return\n    try:\n        parsed = urlparse(candidate)\n        if parsed.scheme in {\"http\", \"https\"}:\n            _ = parsed.port              # raises ValueError for malformed ports\n    except ValueError as exc:\n        raise RuntimeError(\n            f\"Malformed custom endpoint URL: {candidate!r}. \"\n            \"Run `hermes setup` or `hermes model` and enter a valid http(s) base URL.\"\n        ) from exc\n\n\ndef _try_custom_endpoint() -> Tuple[Optional[Any], Optional[str]]:\n    runtime = _resolve_custom_runtime()\n    if len(runtime) == 2:\n        custom_base, custom_key = runtime\n        custom_mode = None\n    else:\n        custom_base, custom_key, custom_mode = runtime\n    if not custom_base or not custom_key:\n        return None, None\n    if custom_base.lower().startswith(_CODEX_AUX_BASE_URL.lower()):\n        return None, None\n    model = _read_main_model_for_aux() or \"gpt-4o-mini\"\n    logger.debug(\"Auxiliary client: custom endpoint (%s, api_mode=%s)\", model, custom_mode or \"chat_completions\")","sourceCodeStart":3531,"sourceCodeEnd":3567,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/auxiliary_client.py#L3531-L3567","documentation":"Pre-flight validation of a custom endpoint base_url in _validate_base_url: any non-empty candidate that is not an acp:// URL must parse with an http/https scheme and a valid port, else urlparse(...).port raises ValueError. Hermes rejects obviously broken URLs before they reach httpx and points the user back to the setup/model wizard as the sanctioned way to change it.","triggerScenarios":"model.base_url (custom endpoint) in config.yaml like 'https://api.example.com:v1' — a host:port segment where the port is not numeric — so parsing raises during _try_custom_endpoint validation.","commonSituations":"Hand-edited config.yaml with a typo'd URL; a pasted URL carrying trailing garbage into the port field; port written as '8080/' after a bad search-replace.","solutions":["Run `hermes setup` or `hermes model` and re-enter a valid http(s) URL such as https://api.example.com/v1","Or hand-fix model.base_url in config.yaml, ensuring a proper scheme and, if present, a numeric port","Verify it parses: python -c \"from urllib.parse import urlparse; urlparse('YOUR_URL').port\""],"exampleFix":"# config.yaml — before\nmodel:\n  base_url: \"https://api.example.com:v1\"\n\n# after\nmodel:\n  base_url: \"https://api.example.com/v1\"","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\ndef base_url_valid(base_url: str) -> bool:\n    candidate = str(base_url or \"\").strip()\n    if not candidate or candidate.startswith(\"acp://\"):\n        return True\n    try:\n        parsed = urlparse(candidate)\n        if parsed.scheme in {\"http\", \"https\"}:\n            _ = parsed.port\n        return parsed.scheme in {\"http\", \"https\"}\n    except ValueError:\n        return False\n\nif not base_url_valid(configured_base_url):\n    reject_config(\"model.base_url\", configured_base_url)","typeGuard":null,"tryCatchPattern":"try:\n    client = _try_custom_endpoint()\nexcept RuntimeError as e:\n    if \"Malformed custom endpoint URL\" in str(e):\n        reopen_model_wizard()  # hermes setup / hermes model re-prompts for the URL\n    else:\n        raise","preventionTips":["Change endpoint URLs only through `hermes setup` / `hermes model`, which validate input","After hand-editing config.yaml, parse the URL in a one-liner to confirm scheme and port","Beware search-replace edits that glue text onto port digits"],"tags":["config","base-url","validation","http"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}