iflytek/astron-agent · error · OutboundPolicyError
Outbound URL must include a hostname
Error message
Outbound URL must include a hostname
What it means
_validate_parsed_http_url (part of the plugin SSRF guard) raises OutboundPolicyError when the parsed outbound URL has no hostname. The link tool's HTTP executor refuses scheme-only/malformed URLs before any network call is made.
Solutions
- Ensure the URL includes a host, e.g. https://api.example.com/path.
- Log the URL before the call and find where the host portion was lost (empty env var, wrong placeholder).
- Fix the upstream configuration or URL-building code so the host is always present.
- Validate host non-empty before invoking the plugin (see validation code).
Example fix
// before
url = f"https://{host}/v1/tools" # host == ""
// after
if not host:
raise ValueError("tool host is required")
url = f"https://{host}/v1/tools" Defensive patterns
Strategy: validation
Validate before calling
def has_hostname(url: str) -> bool:
return bool(urlsplit(url).hostname) Try / catch
try:
client.get(url)
except OutboundPolicyError as e:
raise ConfigError(f"tool endpoint needs a host: {url!r}") from e Prevention
- Check base-URL env vars are non-empty at startup
- Avoid f-string URL building with possibly-empty host variables
- Validate configured endpoints once during service boot
When it happens
Trigger: _parse_http_url gets a URL where urlsplit().hostname is None or empty — e.g. "http:///api", "https://", or a truncated string produced by slicing or template substitution with an empty host variable.
Common situations: Environment variable or tool config holding a truncated URL; f"https://{host}" with empty host; base-URL joining that dropped the domain.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- HTTPClientError
- MODEL_URL_CHECK_FAILED
- MODEL_URL_CHECK_FAILED
- MODEL_URL_ILLEGAL_FAILED
- Only HTTP and HTTPS tool URLs are allowed
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/ae9179f8972c98aa.
Report an issue: GitHub.
Appendix: source
Thrown at core/plugin/link/infra/tool_exector/ssrf_guard.py:204
try:
parsed = urlsplit(url)
port = parsed.port
except (TypeError, ValueError) as exc:
raise OutboundPolicyError("Outbound URL is malformed") from exc
_validate_parsed_http_url(parsed, port)
return parsed
def _validate_url_characters(url: str) -> None:
if any(ord(character) < 0x20 or ord(character) == 0x7F for character in url):
raise OutboundPolicyError("Outbound URL contains control characters")
def _validate_parsed_http_url(parsed: SplitResult, port: Union[int, None]) -> None:
if parsed.scheme.lower() not in _ALLOWED_SCHEMES:
raise OutboundPolicyError("Only HTTP and HTTPS tool URLs are allowed")
if not parsed.hostname:
raise OutboundPolicyError("Outbound URL must include a hostname")
if parsed.username is not None or parsed.password is not None:
raise OutboundPolicyError("Outbound URL must not include user information")
if "\\" in parsed.netloc:
raise OutboundPolicyError("Outbound URL authority is invalid")
if parsed.fragment:
raise OutboundPolicyError("Outbound URL must not include a fragment")
if port is not None and not 1 <= port <= 65535:
raise OutboundPolicyError("Outbound URL port is invalid")
def _parse_networks(raw_value: str, setting_name: str) -> Tuple[IpNetwork, ...]:
networks = []
for entry in raw_value.split(","):
value = entry.strip()
if not value:
continue
try:
networks.append(ipaddress.ip_network(value, strict=False))View on GitHub (pinned to 5e758547a8)