iflytek/astron-agent · error · OutboundPolicyError

Outbound URL port is invalid

Error message

Outbound URL port is invalid

What it means

An explicit port in the URL must be in the valid TCP range 1–65535. (Non-numeric ports make urlsplit .port raise ValueError, handled earlier as 'malformed'.) This error fires when a numeric port outside the range, such as 0 or 70000, reaches validation.

Solutions

  1. Correct the port to 1–65535 (or omit it to use 80/443 defaults).
  2. Validate the port before composing the URL: 1 <= int(port) <= 65535.
  3. Check the environment variable or config supplying the port for typos.
  4. Clamp or reject out-of-range values at config load time if the port is dynamic.

Example fix

// before
url = f"https://api.example.com:{port}/v1"  # port = 70000
// after
if not (1 <= port <= 65535):
    raise ValueError(f"invalid port {port}")
url = f"https://api.example.com:{port}/v1"
Defensive patterns

Strategy: validation

Validate before calling

def port_in_range(url: str) -> bool:
    try:
        port = urlsplit(url).port
    except ValueError:
        return False
    return port is None or 1 <= port <= 65535

Try / catch

try:
    client.get(url)
except OutboundPolicyError as e:
    raise ConfigError(f"invalid port in endpoint: {e}") from e

Prevention

When it happens

Trigger: _parse_http_url gets a URL like http://host:0/, http://host:65536/, or http://host:-1/ — the parsed port is not None and fails the 1 <= port <= 65535 check.

Common situations: Port from a misconfigured env var (extra digits, 0 placeholder); port copy-pasted from another protocol context; string concatenation producing an oversized port number.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/caa69c7e6e162387. Report an issue: GitHub.

Appendix: source

Thrown at core/plugin/link/infra/tool_exector/ssrf_guard.py:212

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))
        except ValueError as exc:
            raise OutboundPolicyError(f"Invalid {setting_name} entry") from exc
    return tuple(networks)


def _parse_domains(raw_value: str) -> Tuple[str, ...]:
    domains = []
    for entry in raw_value.split(","):

View on GitHub (pinned to 5e758547a8)