neondatabase/neon · error

Error parsing {remote_endpoint}, expected host:port, got {er

Error message

Error parsing {remote_endpoint}, expected host:port, got {err:?}

What it means

parse_audit_syslog_address builds the synthetic URL `http://{remote_endpoint}` from AUDIT_LOGGING_ENDPOINT / AUDIT_LOGGING_TLS_ENDPOINT and calls Url::parse; this error means even that synthetic URL failed to parse. Practically the endpoint contains characters a URL cannot hold - repeated colons ('collector.host.tld:::5555'), spaces, control characters - or is structurally broken. The {:?} payload carries the url::ParseError variant (e.g. InvalidDomainCharacter, InvalidPort).

Source

Thrown at compute_tools/src/rsyslog.rs:102

    Ok(())
}

fn parse_audit_syslog_address(
    remote_plain_endpoint: &str,
    remote_tls_endpoint: &str,
) -> Result<(String, u16, String)> {
    let tls;
    let remote_endpoint = if !remote_tls_endpoint.is_empty() {
        tls = "true".to_string();
        remote_tls_endpoint
    } else {
        tls = "false".to_string();
        remote_plain_endpoint
    };
    // Urlify the remote_endpoint, so parsing can be done with url::Url.
    let url_str = format!("http://{remote_endpoint}");
    let url = Url::parse(&url_str).map_err(|err| {
        anyhow!("Error parsing {remote_endpoint}, expected host:port, got {err:?}")
    })?;

    let is_valid = url.scheme() == "http"
        && url.path() == "/"
        && url.query().is_none()
        && url.fragment().is_none()
        && url.username() == ""
        && url.password().is_none();

    if !is_valid {
        return Err(anyhow!(
            "Invalid address format {remote_endpoint}, expected host:port"
        ));
    }
    let host = match url.host() {
        Some(Host::Domain(h)) if hostname_validator::is_valid(h) => h.to_string(),
        Some(Host::Ipv4(ip4)) => ip4.to_string(),
        Some(Host::Ipv6(ip6)) => ip6.to_string(),

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Set the endpoint strictly as host:port, e.g. collector.host.tld:5555
  2. For IPv6 addresses always bracket them: [7e60:82ed:...]:5555
  3. Read the ParseError debug in the message to see which character class broke parsing
  4. Pre-validate the env value with a host:port parser before compute start

Example fix

# before
AUDIT_LOGGING_ENDPOINT=collector.host.tld:::5555

# after
AUDIT_LOGGING_ENDPOINT=collector.host.tld:5555
Defensive patterns

Strategy: validation

Validate before calling

// reject malformed endpoints before touching rsyslog
fn is_host_port(endpoint: &str) -> bool {
    let Some((host, port)) = endpoint.rsplit_once(':') else { return false };
    let host = host.trim_start_matches('[').trim_end_matches(']');
    let host_ok = hostname_validator::is_valid(host)
        || host.parse::<std::net::Ipv4Addr>().is_ok()
        || host.parse::<std::net::Ipv6Addr>().is_ok();
    host_ok && port.parse::<u16>().is_ok()
}

if !is_host_port(&remote_endpoint) {
    bail!("audit endpoint must be host:port, got {remote_endpoint:?}");
}

Type guard

fn is_host_port(endpoint: &str) -> bool {
    let Some((host, port)) = endpoint.rsplit_once(':') else { return false };
    let host = host.trim_start_matches('[').trim_end_matches(']');
    (hostname_validator::is_valid(host)
        || host.parse::<std::net::Ipv4Addr>().is_ok()
        || host.parse::<std::net::Ipv6Addr>().is_ok())
        && port.parse::<u16>().is_ok()
}

Try / catch

let url = match Url::parse(&format!("http://{remote_endpoint}")) {
    Ok(u) => u,
    Err(err) => return Err(anyhow!("invalid endpoint {remote_endpoint}: {err:?}")),
};

Prevention

When it happens

Trigger: Url::parse of 'http://{endpoint}' fails: multiple colons ('host:::514'), illegal characters in host/port, percent-mangled values, or garbage strings from env vars.

Common situations: Typoed or copy-pasted audit endpoint env values; values that already include a scheme or multiple separators; CI configurations injected with quoting artifacts.

Related errors


AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16). Data as JSON: /api/errors/a35044984308b4af. Report an issue: GitHub.