stamparm/maltrail · error

unable to resolve remote logging endpoint

Error message

unable to resolve remote logging endpoint '{endpoint}'

What it means

The remote logging endpoint's hostname could not be resolved to an address. endpoint_addr caches resolved endpoints and backs off failed lookups for ENDPOINT_RETRY_INTERVAL; when resolution fails it logs this error, returns None, and the datagram for that event is dropped for now.

Solutions

  1. Verify the remote logging endpoint hostname in sensor configuration is correct and resolvable (dig/nslookup from the sensor host).
  2. Fix DNS on the sensor host (check /etc/resolv.conf, firewall rules to the resolver).
  3. The sensor retries resolution after ENDPOINT_RETRY_INTERVAL — confirm the error clears itself after transient DNS outages.
  4. Pre-resolve and configure an IP literal for the endpoint if DNS is unreliable in the deployment.
Defensive patterns

Strategy: retry

Validate before calling

# verify the configured remote logging endpoint resolves, from the sensor host
dig +short "$REMOTE_LOG_HOST"
# non-empty output means DNS is healthy for the endpoint

Prevention

When it happens

Trigger: send_datagram requests an endpoint not present in the cache, and ToSocketAddrs-style resolution of the configured '{endpoint}' returns None — bad hostname, no DNS, or no network at that moment. The endpoint is queued for retry after ENDPOINT_RETRY_INTERVAL.

Common situations: DNS server unreachable on the sensor host; typo in the remote log host config; endpoint hostname removed from DNS; sensor deployed in a network-isolated environment where only a local event log works.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13). Data as JSON: /api/errors/5960ab8c6c525df3. Report an issue: GitHub.

Appendix: source

Thrown at sensor/src/output.rs:477

    /// every subsequent detection, silently.
    fn endpoint_addr(&mut self, endpoint: &str) -> Option<SocketAddr> {
        if let Some(addr) = self.endpoints.get(endpoint) {
            return Some(*addr);
        }
        let now = Instant::now();
        if let Some(deadline) = self.endpoint_retry.get(endpoint) {
            if now < *deadline {
                return None;
            }
        }
        match resolve_endpoint(endpoint) {
            Some(addr) => {
                self.endpoints.insert(endpoint.to_string(), addr);
                self.endpoint_retry.remove(endpoint);
                Some(addr)
            }
            None => {
                log_error(&format!("unable to resolve remote logging endpoint '{endpoint}'"), true);
                self.endpoint_retry.insert(endpoint.to_string(), now + Self::ENDPOINT_RETRY_INTERVAL);
                None
            }
        }
    }

    fn send_datagram(&mut self, endpoint: &str, data: &[u8]) {
        let Some(addr) = self.endpoint_addr(endpoint) else {
            self.remote_log_errors += 1;
            return;
        };

        let is_v6 = addr.is_ipv6();
        let bind: &str = if is_v6 { "[::]:0" } else { "0.0.0.0:0" };
        let sock = if is_v6 { &mut self.sock6 } else { &mut self.sock4 };
        if sock.is_none() {
            *sock = UdpSocket::bind(bind).ok();
        }

View on GitHub (pinned to 77cfb06d76)